Глава 4. Встроенный язык

«1С:Предприятие» является гибкой настраиваемой системой, с помощью которой можно решать широкий круг задач в сфере автоматизации деятельности предприятий. Специфические алгоритмы конфигурации описываются в конфигураторе системы «1С:Предприятие», в программных модулях, содержащих тексты на встроенном языке системы «1С:Предприятие».

4.1. Назначение и краткая характеристика встроенного языка

Встроенный язык системы «1С:Предприятие» предназначен для описания (на стадии разработки конфигурации) алгоритмов функционирования прикладной задачи.

Встроенный язык (далее по тексту ‑ язык) представляет собой предметно-ориентированный язык программирования, специально разработанный с учетом возможности его применения не только профессиональными программистами. В частности, все операторы языка имеют как русское, так и англоязычное написание, которое можно использовать одновременно в одном исходном тексте. Основной язык, описываемый в данной книге, ‑ русский, однако для каждого оператора языка приводится его англоязычный синоним.

При своей относительной простоте язык обладает некоторыми объектно-ориентированными возможностями, например, правила доступа к свойствам и методам специализированных типов данных (документам, справочникам и т. п.) подобны свойствам и методам объектов, используемых в других объектно-ориентированных языках. Однако специализированные типы данных не могут определяться средствами самого языка, а задаются в визуальном режиме.

Типизация переменных в языке не жесткая, т. е. тип переменной определяется ее значением. Переменные не обязательно объявлять в явном виде. Неявным определением переменной является ее первое упоминание в левой части оператора присваивания. Возможно также явное объявление переменных при помощи соответствующего оператора. Допускается применение массивов, структур, соответствий и других универсальных коллекций значений.

4.2. Формат исходных текстов программных модулей

4.2.1. Что такое программный модуль

Программные модули в конфигурации системы «1С:Предприятие» не являются самостоятельными программами в общепринятом понимании этого слова, поскольку они являются только частью всей конфигурации. Программный модуль ‑ это текст на встроенном языке, в котором размещены тексты процедур и функций с необходимыми алгоритмами, вызываемые системой в определенные моменты работы. Поэтому программный модуль не имеет формальных границ своего описания типа: «Начало модуля» ‑ «Конец модуля».

Место размещения конкретного программного модуля предоставляется конфигуратором в тех точках конфигурации, которые требуют описания специфических алгоритмов функционирования. Эти алгоритмы следует оформлять в виде процедур или функций, которые будут вызваны самой системой в заранее предусмотренных ситуациях (например, при нажатии кнопки в диалоговом окне).

Каждый отдельный программный модуль воспринимается системой как единое целое, поэтому все процедуры и функции программного модуля выполняются в едином контексте.

4.2.2. Контекст выполнения программного модуля

Каждый программный модуль связан с остальной частью конфигурации. Эта связь называется контекстом выполнения модуля.

Следует различать два вида контекста:

● глобальный контекст,

● локальный контекст выполнения конкретного модуля.

4.2.2.1. Глобальный контекст

Глобальный контекст образуется:

● значениями свойств и методов глобального контекста;

● системными перечислениями и системными наборами значений (например, КодВозвратаДиалога и Символы).

Глобальный контекст виден всем программным модулям и определяет общую языковую среду конфигурации.

4.2.2.2. Локальный контекст

Локальный контекст модуля образуется тем конкретным местом конфигурации задачи, для которого использован программный модуль. Локальный контекст виден только конкретному программному модулю и определяет для модуля набор непосредственно доступных модулю объектов, их свойств и методов.

4.2.3. Виды программных модулей

В системе «1С:Предприятие» существуют несколько видов программных модулей. Они различаются по месту размещения и доступному контексту.

4.2.3.1. Модуль управляемого приложения

Модулем управляемого приложения называется модуль, который автоматически выполняется в момент загрузки конфигурации, при старте системы «1С:Предприятие» в следующих режимах:

● тонкого клиента,

● веб-клиента,

● толстого клиента в режиме управляемого приложения.

Модуль управляемого приложения предназначен для отработки действий, связанных с сеансом работы конечного пользователя (прежде всего обработки начала и окончания сеанса работы). Модуль управляемого приложения недоступен для процедур, работающих на сервере. В нем рекомендуется реализовывать только обработчики соответствующих событий. Следует помнить, что необработанное исключение в каком-либо обработчике события модуля управляемого приложения (ПередНачаломРаботыСистемы(), ПриНачалеРаботыСистемы(), ПередЗавершениемРаботыСистемы(), ПриЗавершенииРаботыСистемы()) приведет к аварийному завершению работы всей системы.

Например, в следующем примере аварийного завершения не произойдет:

Копировать в буфер обмена
Процедура ПриНачалеРаботыСистемы()
    Попытка
   а=1/0;
    Исключение
   Сообщить("Деление на 0");
    КонецПопытки;
КонецПроцедуры

В то же время следующий пример приведет к аварийному завершению:

Копировать в буфер обмена
Процедура ПриНачалеРаботыСистемы()
    а=1/0;
КонецПроцедуры

Процедуры, функции и переменные модуля управляемого приложения, для которых в заголовке указано ключевое слово Экспорт, являются доступными:

● в неглобальных клиентских общих модулях,

● клиентских процедурах и функциях модуля команды,

● клиентских процедурах и функциях модуля управляемой формы.

В контексте модуля управляемого приложения доступны:

● часть глобального контекста, которая может исполняться в управляемом приложении;

● экспортируемые процедуры и функции любых клиентских общих модулей;

● экспортируемые процедуры и функции серверных неглобальных общих модулей, у которых установлено свойство Вызов сервера.

4.2.3.2. Модуль внешнего соединения

Модуль внешнего соединения расположен, как и модуль приложения, в корневом разделе конфигурации. В нем располагаются процедуры-обработчики событий, которые инициализируются при старте и окончании работы системы в режиме внешнего соединения (СОМ-соединения).

В модуле внешнего соединения возможно объявление переменных, а также объявление и описание процедур и функций, которые будут доступны для внешнего приложения.

Объекты «1С:Предприятия», доступные извне через COM-соединение:

● экспортируемые процедуры/функции модуля внешнего соединения;

● экспортируемые процедуры/функции общих модулей:

● включение и исключение модулей целиком выполняются с помощью установки свойств общих модулей;

● включение и исключение фрагментов общих модулей выполняются с помощью инструкций препроцессора;

● глобальный контекст «1С:Предприятия».

Модуль присутствует только в сессии внешнего соединения. В данном режиме характерно полное отсутствие пользовательского интерфейса.

4.2.3.3. Модуль сеанса

Модулем сеанса называется модуль, который автоматически выполняется при старте системы «1С:Предприятие» в момент загрузки конфигурации.

Модуль сеанса предназначен для инициализации параметров сеанса и отработки действий, связанных с сеансом работы. Этот общий модуль всегда исполняется в привилегированном режиме сервера «1С:Предприятия». Установка параметров сеанса выполняется в обработчике события УстановкаПараметровСеанса.

Модуль сеанса может содержать только определения процедур и функций, может использовать процедуры из общих модулей конфигурации и не содержит экспортируемых процедур и функций.

Вызов обработчика УстановкаПараметровСеанса() производится до вызова обработчика события ПередНачаломРаботыСистемы() (ПриНачалеРаботыСистемы() в случае модуля внешнего соединения).

При выполнении обработчика события УстановкаПараметровСеанса может возникнуть необходимость определить, какой сеанс стартует: фонового задания или какой-либо другой. Это может потребоваться в том случае, если объем инициализируемых данных фонового задания существенно отличается от объема инициализируемых данных других сеансов. Определить тип сеанса можно с помощью методов ПолучитьТекущийСеансИнформационнойБазы() и ПолучитьФоновоеЗадание(). Первый метод возвращает описание текущего сеанса ‑ объект СеансИнформационнойБазы. Вызов метода ПолучитьФоновоеЗадание() у полученного объекта позволит однозначно понять, стартует сеанс фонового задания или какой-либо другой сеанс.

4.2.3.4. Общие модули

Общие модули располагаются в отдельной ветке дерева метаданных. Основным назначением общих модулей является содержание общих алгоритмов конфигурации, доступных из разных модулей. В общих модулях отсутствует раздел определения переменных и раздел основной программы, то есть они содержат только раздел процедур и функций (см. раздел «Структура программного модуля»).

В любом общем модуле возможно объявление и описание процедур и функций, которые будут доступны в любом модуле конфигурации.

Подробнее про общие модули см. здесь.

4.2.3.5. Модули прикладных объектов

Набор прикладных объектов имеет собственные модули. К таким объектам относятся:

● Менеджеры значения константы,

● Справочники,

● Документы,

● Отчеты,

● Обработки,

● Планы видов характеристик,

● Планы счетов,

● Планы видов расчетов,

● Планы обмена,

● Бизнес-процессы,

● Задачи,

● Регистры.

Модули располагаются в ветках конфигурации, в которых содержатся сами объекты, и являются свойствами объектов. Каждый объект имеет свой индивидуальный модуль. В этих модулях возможно объявление переменных, процедур и функций, которые будут доступны при работе с объектом извне во встроенном языке, дополняя контекст объекта.

В контексте модуля прикладного объекта имеется доступ к реквизитам и табличным частям объекта, а также его методам и событиям.

4.2.3.6. Модули менеджеров объектов

Каждый прикладной объект имеет менеджер, предназначенный для управления этим объектом как объектом конфигурации. С помощью менеджера можно создавать объекты, работать с формами и макетами. Модуль менеджера позволяет расширить функциональность менеджеров за счет введения процедур и функций на встроенном языке. Фактически это позволяет описать методы для объекта конфигурации (например, справочника), которые относятся не к конкретному экземпляру объекта базы данных, а к самому объекту конфигурации.

Контекст модуля менеджера образуется:

● свойствами и методами глобального контекста;

● экспортируемыми процедурами и функциями глобальных общих модулей (если эти модули компилируются на сервере);

● экспортируемыми процедурами и функциями неглобальных общих модулей (если эти модули компилируются на сервере);

● локальным контекстом самого модуля.

Модуль менеджера не может иметь переменных и тела модуля.

Если функции или процедуры модуля менеджера объявлены как экспортируемые, к ним можно будет получить доступ через менеджер объекта.

Например, опишем функцию в модуле менеджера справочника Контрагенты:

Копировать в буфер обмена
Функция ПолучитьСписокДебиторов() ЭкспортКонецФункции

Тогда вызов этой функции из прикладного кода будет выглядеть следующим образом:

Копировать в буфер обмена
Дебиторы = Справочники.Контрагенты.ПолучитьСписокДебиторов();

4.2.3.7. Модули форм

Эти модули содержатся в формах конфигурации (см. здесь). Каждая форма имеет свой индивидуальный модуль. В этих модулях возможно объявление переменных, процедур и функций, которые будут доступны при работе с формой извне во встроенном языке, дополняя контекст формы.

Контекст формы будет образован:

● локальным контекстом самого модуля формы, реквизитами формы, которой «принадлежит» модуль;

● свойствами и методами объекта ФормаКлиентскогоПриложения встроенного языка;

● свойствами и методами расширения формы, определяемого типом того объекта, данные которого содержатся в основном реквизите формы;

● глобальным контекстом, в том числе неглобальными общими модулями и экспортируемыми функциями и процедурами глобальных общих модулей, при этом нужно обеспечивать согласованность того, как описана процедура в модуле формы (&НаКлиенте, &НаСервере и т. д.), и того, какие свойства установлены у общего модуля (Клиент (управляемое приложение), Сервер и т. д.);

● экспортируемыми переменными, процедурами и функциями модуля управляемого приложения.

4.2.3.8. Модули команд

Модуль команды предназначен для того, чтобы описать в нем на встроенном языке те действия, которые должна выполнить система при вызове команды. Модуль команды может содержать только описание процедур и функций. Модуль команды не может иметь переменных и тела модуля.

Обработчик ОбработкаКоманды() обязательно должен предваряться инструкцией препроцессора &НаКлиенте, т. к. именно там начинается исполнение команды.

Контекст клиентских процедур модуля команды образуется:

● глобальным контекстом, в том числе неглобальными общими модулями и экспортируемыми функциями и процедурами глобальных общих модулей, при этом нужно обеспечивать согласованность того, как описана процедура в модуле формы (&НаКлиенте, &НаСервере и т. д.), и того, какие свойства установлены у общего модуля (Клиент (управляемое приложение), Сервер и т. д.);

● локальным контекстом самого модуля команды.

Контекст серверных процедур модуля команды образуется:

● свойствами и методами глобального контекста;

● экспортируемыми процедурами и функциями глобальных общих модулей, если эти модули компилируются на сервере;

● неглобальными общими модулями, если эти модули компилируются на сервере; доступны экспортируемые методы таких модулей;

● серверными методами модуля команды.

В модуле команды можно описывать методы с ключевым словом Экспорт. Однако как-либо использовать их за пределами этого модуля нельзя. Из встроенного языка невозможно получить доступ к командам и, следовательно, к их контексту тоже.

4.2.4. Формат программного модуля

Структуру программного модуля можно подразделить на следующие разделы:

● раздел определения переменных,

● раздел процедур и функций,

● раздел основной программы.

В конкретном программном модуле любой из разделов может отсутствовать.

Раздел определения переменных размещается от начала текста модуля до первого оператора Процедура, или оператора Функция, или любого исполняемого оператора. В этом разделе могут находиться только операторы объявления переменных Перем.

Раздел процедур и функций размещается от первого оператора Процедура или оператора Функция до любого исполняемого оператора вне тела описания процедур или функций.

Раздел основной программы размещается от первого исполняемого оператора вне тела последней процедуры или функции до конца модуля. В этом разделе могут находиться только исполняемые операторы. Раздел основной программы исполняется в момент инициализации модуля. Обычно в разделе основной программы имеет смысл размещать операторы инициализации переменных какими-либо конкретными значениями, которые необходимо провести до первого вызова любой из процедур или функций модуля.

Исходный текст программного модуля может состоять из операторов и комментариев.

4.2.4.1. Комментарии

Комментарий используется для размещения в исходном тексте программного модуля всякого рода пояснений к работе модуля. Хорошим тоном программирования считается, когда исходный текст содержит исчерпывающий комментарий с описанием алгоритма. В режиме исполнения программы комментарии пропускаются. В тексте программного модуля комментарий начинается парой символов «//» и заканчивается концом строки. Это значит, что комментарий можно начинать с начала строки или записывать его после оператора на той же строке. После начала комментария нельзя писать оператор на той же строке, необходимо закончить комментарий концом строки.

Копировать в буфер обмена
А=В; // Это - комментарий
// Это тоже комментарий

Комментарий, предшествующий процедуре или функции, может использоваться контекстной подсказкой конфигуратора. Формат такого комментария и схема работы см. здесь.

4.2.4.2. Формат операторов

Операторы имеют вид стандартного обращения к процедуре, за исключением оператора присваивания (А = В;) и синтаксических конструкций встроенного языка (например, таких как Для, Пока, Если). Между собой операторы обязательно следует разделять символом точка с запятой. Конец строки не является признаком конца оператора, т. е. операторы могут свободно переходить через строки и продолжаться на другой строке. Можно располагать произвольное число операторов в одной строке, разделяя их символом точка с запятой.

Операторы языка в программном модуле можно подразделить на две категории: операторы объявления переменных и исполняемые операторы.

Операторы объявления переменных создают имена переменных, которыми манипулируют исполняемые операторы.

Любой исполняемый оператор может иметь метку, используемую в качестве точки перехода в операторе Перейти.

В общем случае формат оператора языка следующий:

Копировать в буфер обмена
~метка:Оператор[(параметры)] [ДобКлючевоеСлово];

В качестве меток используются специальные идентификаторы, начинающиеся с символа тильда и состоящие из последовательности букв, цифр и символов подчеркивание. Чтобы пометить оператор, нужно поместить перед ним метку и следующий за ней символ двоеточие.

Копировать в буфер обмена
~метка:А=В;

4.2.4.3. Имена переменных, процедур и функций

Именем переменной, объявленной процедуры или функции может быть любая последовательность букв, цифр и знаков подчеркивания, начинающаяся с буквы или знака подчеркивания. Вновь создаваемые имена не должны совпадать с зарезервированными словами языка, а также именами свойств, процедур и функций (включая имена обработчиков событий), непосредственно доступных в текущем контексте. Распознавание имен переменных, процедур и функций ведется без учета регистра букв.

4.2.4.4. Язык написания программных модулей

Встроенный язык системы «1С:Предприятие» является двуязычным. Почти все зарезервированные слова, имена типов значений, свойств, методов, событий имеют два имени: русское и английское. Исключение составляют слова, не имеющие аналогов в русском языке. В тексте программных модулей эти имена можно свободно смешивать, используя то русские, то английские имена без каких-либо ограничений.

4.2.4.5. Регистры букв при написании программных модулей

Регистр букв (строчные или заглавные) при написании имен переменных, свойств, методов, процедур, функций, а также функций встроенного языка не имеет значения.

4.2.4.6. Зарезервированные слова

Приведенные далее ключевые слова являются зарезервированными и не могут использоваться в качестве создаваемых имен переменных, реквизитов объектов конфигурации и объявляемых процедур и функций. В данном варианте языка каждое из ключевых слов имеет два представления ‑ русское и английское.

Русское имя

Английское имя

Если

If

Тогда

Then

ИначеЕсли

ElsIf

Иначе

Else

КонецЕсли

EndIf

Для

For

Каждого

Each

Из

In

По

To

Пока

While

Цикл

Do

КонецЦикла

EndDo

Процедура

Procedure

Функция

Function

КонецПроцедуры

EndProcedure

КонецФункции

EndFunction

Перем

Var

Перейти

Goto

Возврат

Return

Продолжить

Continue

Прервать

Break

И

And

Или

Or

Не

Not

Попытка

Try

Исключение

Except

ВызватьИсключение

Raise

КонецПопытки

EndTry

Новый

New

Выполнить

Execute

Примечание. Регистр букв (строчные или заглавные) при написании не имеет значения.

4.2.5. Специальные символы, используемые в исходном тексте

Символ

Описание

//

Двумя знаками косая черта начинается комментарий. Комментарием считается весь текст от символа до конца текущей строки

|

Используется только в строковых константах в начале строки и означает, что данная строка является продолжением предыдущей (перенос строки)

~

Начало метки оператора

:

Окончание метки оператора

;

Символ разделения операторов

( )

В круглые скобки заключается список параметров методов, процедур, функций и конструкторов.

Также они используются в выражениях встроенного языка

[ ]

С помощью оператора квадратные скобки производится обращение к свойствам объекта по строковому представлению имени свойства.

Также возможно обращение к элементам коллекций по индексу или другому параметру

,

Разделяет параметры в списке параметров методов, процедур, функций и конструкторов

" "

Обрамляет строковые литералы

' '

Обрамляет литералы даты

.

Десятичная точка в числовых литералах.

Разделитель, используемый для обращения к свойствам и методам объектов встроенного языка

+

Операция сложения.

Операция конкатенации строк

-

Операция вычитания

*

Операция умножения

/

Операция деления

%

Получение остатка от деления. Допускается использование дробных значений делимого и делителя

>

Логическая операция Больше

>=

Логическая операция Больше или равно

<

Логическая операция Меньше

<=

Логическая операция Меньше или равно

=

Операция присваивания.

Логическая операция Равно

<>

Логическая операция Не равно

4.3. Типы данных и переменные

4.3.1. Общая информация

Тип определяет множество значений, относящихся к данному типу и набор операций, которые можно выполнять над значениями данного типа. Переменная ‑ это ссылка на область памяти, которая хранит значение какого-либо типа. Собственно значение не изменяет своего типа с момента создания. Для идентификации переменной служит имя переменной. Так как в системе «1С:Предприятие» используется динамическая типизация, то переменная в каждый конкретный момент времени может ссылаться на значения разных типов. Если переменной до использования не выполнялось присваивание какого-либо значения, то такая переменная содержит значение Неопределено. В системе «1С:Предприятие» все является объектом. Другими словами, любое значение, относящееся к тому или иному типу, представляет собой объект (как и значение типа Тип). В документации возможно упоминание слов «значение» и «объект» в качестве синонимов. С учетом этого замечания можно сказать, что переменная содержит ссылку на объект (или на значение). И фразу «значение переменной» можно понимать следующим образом: значение переменной это объект, расположенный в некотором месте оперативной памяти, ссылка на которое хранится в переменной.

Типы бывают мутабельными (изменяемыми) и иммутабельными (неизменяемыми). Иммутабельный тип ‑ это тип, для которого после создания значения невозможно изменить состояние объекта. Подмножеством иммутабельных типов являются примитивные типы: Неопределено, NULL, Число, Дата, Строка, Булево. Если, например, со значением типа Число выполняется какая-либо операция ‑ создается новое значение типа Число, но не происходит модификации уже существующего объекта. В то же время примером мутабельного типа служит, например, тип, описывающий какой-либо элемент справочника (подробнее см. здесь). Мутабельный тип позволяет изменять состояние объекта этого типа, не создавая нового объекта. Еще одно различие между объектами мутабельных и иммутабельных типов заключается в том, как выполняется сравнение этих объектов:

● Значения иммутабельных типов сравниваются «по значению», поэтому значения разных переменных типа Число будут равны, если для создания каждого значения использовалось одно и тоже значение числа.

● Значения мутабельных типов сравниваются «по ссылке». Другими словами, сравниваются адреса памяти, где размещаются значения. Таким образом, два значения мутабельного типа, даже ссылающихся на один и тот же физический элемент данных (например, элемент справочника с одной и той же ссылкой), всегда не равны друг-другу. Значение мутабельного типа равно только само себе.

Также следует упомянуть о понятии ссылочного типа данных. Ссылочный тип данных не хранит собственно значение объекта, он содержит только некоторый ключ, позволяющий получить значение из базы данных. Получение объекта по ссылке будет называться разыменованием. В имени ссылочного типа будет явно указан термин Ссылка: СправочникСсылка, ПеречислениеСсылка и т. д. Ссылочный тип является иммутабельным.

Примитивные типы системы «1С:Предприятие» описаны далее в этом разделе. Описание мутабельных типов приводится в других главах и разделах данного руководства. Для всех примитивных типов данных предусмотрена возможность использования в тексте модуля литералов, то есть указание значения соответствующего типа непосредственно в модуле.

Копировать в буфер обмена
// Пример использования литерала типа Строка
А = "Моя строка";
// Пример использования литерала типа Булево
Б = Истина;
// Пример использования литерала типа Число
В = 12345.6789;

4.3.2. NULL

Описание:

Значения данного типа используются исключительно для определения отсутствующего значения при работе с базой данных, например, при соединении таблиц.

Литералы:

NULL

4.3.3. Булево

Описание:

Значения данного типа имеют два значения ‑ Истина и Ложь, задаваемых соответствующими литералами. Значения данного типа возвращаются в качестве результата вычисления логических выражений.

Примечание:

В операциях сравнения встроенного языка используются логические выражения. Это означает, что в выражении сравнения не обязательно писать так:

Копировать в буфер обмена
Если МояПеременная = Истина Тогда
КонецЕсли;

Достаточно написать так:

Копировать в буфер обмена
Если МояПеременная Тогда
КонецЕсли;

Литералы:

Истина (True),

Ложь (False).

4.3.4. Дата

Описание:

Значения данного типа содержат дату от Рождества Христова (с 01 января 0001 года) и время с точностью до секунды. Значение типа Дата, которое хранится в переменной, содержит дату от Рождества Христова с точностью до ста микросекунд. В базе данных значение хранится с точностью до секунды. Не рекомендуется использовать в арифметических операциях с датами числовые значения с дробной частью.

Литералы:

Строка цифр, заключенная в одинарные кавычки вида ‘ГГГГММДДччммсс’, где:

ГГГГ ‑ четыре цифры года (включая тысячелетие и век);

ММ ‑ две цифры месяца;

ДД ‑ две цифры даты;

чч ‑ две цифры часа (в 24-часовом формате);

мм ‑ две цифры минут;

сс ‑ две цифры секунд.

Во встроенном языке в литерале типа Дата обязательно должно задаваться значение года, месяца и дня. Допускается опускать либо время целиком, либо только секунды. Если значение секунд не указано, используется значение «0». Для задания даты, соответствующей началу отсчета, достаточно указать '00010101'. В литерале даты игнорируются все значения, отличные от цифр. Разделители в литерале можно указывать для упрощения ввода даты.

Пример:

Копировать в буфер обмена
Дата('2017\03\23 10~45~25') = 23.03.2017 10:45:25
Дата(2017, 03, 23, 10, 45, 25) = 23.03.2017 10:45:25
Дата('2017.03.23 10:45:25') = 23.03.2017 10:45:25
Дата('20170323104525') = 23.03.2017 10:45:25

4.3.5. Неопределено

Описание:

Значение данного типа применяется, когда необходимо использовать пустое значение, не принадлежащее ни к одному другому типу. Например, такое значение изначально имеют реквизиты с составным типом значения. Существует одно-единственное значение данного типа, задаваемое литералом.

Литералы:

Неопределено (Undefined)

4.3.6. Строка

Описание:

Значения данного типа содержат строку произвольной длины в формате Unicode. Строка закодирована в формате UTF-16. При необходимости указания в строке суррогатной пары, следует использовать два вызова функции Символ() с последовательным указанием значения каждого code unit из суррогатной пары.

Литералы:

Литералы строкового типа представляют собой набор символов, заключенных в кавычки. Для задания в строке символа " (кавычка) необходимо записать две кавычки подряд ("").

Кроме того, допускаются «многострочные» строковые константы. В исходном тексте многострочные константы могут задаваться двумя способами:

● Между фрагментами, представляющими отдельные строки многострочной строки, не должно встречаться никаких символов, за исключением пробелов, переводов строки и строк комментариев.

● Каждая отдельная составляющая не замыкается кавычками, а на каждой последующей строке помещен символ переноса строки «|» (вертикальная черта). В этом варианте комментарии допускаются, если строка начинается с символа комментария «//».

Пример:

Копировать в буфер обмена
// Пример строки
МояСтрока = "Это правильная строка";
// Пример 1 многострочной строки
МояМногострочнаяСтрока = "Это
    |правильная
    |многострочная
    |строка";
// Пример 2 многострочной строки
МояМногострочнаяСтрока = "Это тоже" //Это комментарий
    "правильная"
    "многострочная"
    "строка";
// Пример 3 строки с кавычками
НазваниеФирмы = "ООО ""Василек""";
// Пример 4 суррогатная пара
ТекстССуррогатнойПарой = "Иероглиф: " + Символ(55401) + Символ(56997);

Результат вывода на экран или печать строки НазваниеФирмы (пример 3) будет выглядеть следующим образом:

Копировать в буфер обмена
ООО "Василек"

4.3.7. Тип

Описание:

Значения данного типа используются для идентификации типов значений. Это необходимо для определения и сравнения типов. Данный тип не имеет литералов и возвращается функциями встроенного языка ТипЗнч() и Тип().

4.3.8. Число

Описание:

Числовым типом может быть представлено любое десятичное число. Определены основные арифметические операции над данными числового типа: сложение, вычитание, умножение и деление.

ВНИМАНИЕ! Максимально допустимая разрядность числа ‑ 32 знака.

Литералы:

Набор цифр, написанных непосредственно в тексте модуля вида:

[+|-]{0|1|2|3|4|5|6|7|8|9}[.{0|1|2|3|4|5|6|7|8|9}]

В качестве разделителя целой и дробной части используется точка.

Пример:

Копировать в буфер обмена
А = 15;
Б = -968.612;

4.3.9. Конвертация значения в строку и обратно

Любое значение в системе «1С:Предприятие» имеет свое текстовое представление. Представления некоторых объектов заданы в самой платформе и не могут быть изменены (например, это системные перечисления), для некоторых объектов представление может управляться с помощью свойств объекта или встроенного языка (например, справочники), представление некоторых объектов зависит от языка текущего сеанса (например, числа, даты, булево). Значение автоматически преобразуется в свое представление в том случае, когда это значение отображается пользователю или присваивается объекту, имеющему тип Строка. В этом случае происходит неявное преобразование значения к типу Строка. Имеется возможность явно вызвать такое преобразование. Для этого следует явно использовать конструктор объекта типа Строка, передав ему в качестве параметра требуемое значение.

Следует обратить внимание, что значения некоторых типов могут быть преобразованы и в обратную сторону: из строки в значение соответствующего типа. К таким типам относятся: Строка, Число, Дата и Булево. Рассмотрим подробнее, как выполняется и что влияет на конвертацию значений этих типов в строку и обратно.

Самым простым типом, с точки зрения конвертации, является тип Строка. Как таковой конвертации там нет.

Преобразование в строку для типов Число, Дата и Булево определяется двумя способами ‑ явным указанием параметров преобразования для функции Формат() и региональными установками информационной базы. Региональные установки изменяют представления вышеуказанных типов сразу и везде в клиентском приложении. Таким образом, одно и тоже значение, которое преобразуется в строку, будет давать в результате разное значение, которое зависит от региональных настроек (или языка, на котором отображается интерфейс клиентского приложения ‑ языка локализации).

Например, для типа Булево, значение Истина будет представлено как Да для русского интерфейса и Yes ‑ для английского. Если в диалоге региональных установок переопределено представление значения типа Булево, например, на Non (для Ложь) и Oui (для Истина), то для любого языка локализации будут отображаться именно эти значения.

Аналогичное поведение наблюдается и для типов Число и Дата: используется или представление, определяемое настройками сеанса или явно заданные параметры локализации.

Обратная конвертация (из строки в значение типа Булево, Число, Дата) выполняется более сложным образом. Строка может принимать преобразуемое значение в каноническом или локализованном виде. Канонический вид ‑ это такой вид, который полностью соответствует представлению соответствующего типа в виде литералов встроенного языка. Локализованный вид ‑ это вид, который получен в результате преобразования значения в строку с учетом региональных настроек. Из этого утверждения следует, что преобразование «значение -> строка ‑> значение» в общем случае не сработает, если локализация при первом преобразовании отличается от локализации при втором преобразовании или отличаются настройки локализации. Поясним это на примере типа Булево, но прежде приведем таблицу, в которой для каждого типа указаны канонические представления типа:

Тип

Каноническое представление

Булево

Значение Истина: Истина, True.

Значение Ложь: Ложь, False.

Подробнее см. здесь.

Число

Десятичное число, которое может иметь знак (символы "-" или "+") в качестве префикса и в котором необязательная дробная часть отделяется от целой части символом ".".

Подробнее см. здесь.

Дата

Представление, совпадающее с представлением в виде литерала встроенного языка.

Подробнее см. здесь.

Если мы преобразуем в сроку значение Истина для русской локализации, то получим значение Да. Если мы попробуем выполнить обратное преобразование с английской локализацией, то получим ошибку времени исполнения. В том случае, если в региональных установках информационной базы изменено представление значения типа Булево, то будет наблюдаться ровно такая же картина! Если для примера выше (Non и Oui) выполнить попытку обратного преобразования для строк Yes или Да ‑ то результатом будет ровно такая же ошибка времени исполнения.

Из описанного поведения следует несколько важных выводов:

1. Для максимальной переносимости не следует использовать локализуемые представления значений при самостоятельной сериализации значений в текстовые форматы. Можно использовать методы XMLСтрока() и XMLЗначение().

2. При сохранении значений в текстовом виде и при необходимости восстановления этих значений из встроенного языка, не следует менять региональные установки информационной базы после того, как выполнено сохранение значений. В противном случае прочитать эти значения будет невозможно.

3. Локализованные значения по умолчанию не являются корректным значением для преобразования из строки, если изменены соответствующие разделы региональных установок.

Смотри также:

● Региональные установки информационной базы (см. здесь).

4.4. Оператор присваивания

Оператор присваивания (=)

Описание:

Оператор присваивания (символ «=») означает присваивание значения <Источник> переменной, обозначенной как <Назначение>.

Присвоение значения необъявленной переменной, совпадающей по имени со свойством, доступном в текущем контексте, может диагностироваться как ошибка времени выполнения или во время проверки конфигурации. Чтобы избежать появления ошибок, рекомендуется явно объявлять переменные с такими именами с помощью оператора Перем.

Синтаксис:

<Назначение> = <Источник>;

Параметры:

<Назначение>

В качестве назначения может выступать переменная или свойство объекта встроенного языка, которое допускает запись.

<Источник>

Выражение, значение которого необходимо присвоить.

Пример:

Копировать в буфер обмена
А = В;
Стр1 = "777";
ДатаДокумента = '20020717';

4.5. Выражения языка

Выражение ‑ это математическая, логическая или строковая формула, состоящая из соответствующих операций, по которой вычисляется значение. Математическое и логическое выражение может стоять справа от знака равенства в операторах присваивания, быть параметром процедур или функций. Логическое выражение также может быть условием в управляющих конструкциях Если, Пока, Для. Выражения состоят из констант, переменных и функций, связанных символами логических и/или арифметических операций.

4.5.1. Арифметические операции

В языке определены следующие виды арифметических операций.

Название

Выражение

Сложение

(Оп1 + Оп2)

Вычитание

(Оп1 ‑ Оп2)

Умножение

(Оп1 * Оп2)

Деление

(Оп1 / Оп2)

Остаток от деления

(Оп1 % Оп2)

Унарный минус

(-Оп1)

Арифметические операции имеют один или два операнда, в зависимости от типа которых операция имеет ту или иную семантику. Тот или иной семантический вариант операции определяется по первому операнду. В случае несовпадения типа второго операнда с требуемым значение преобразуется к требуемому типу в соответствии с правилами преобразования типов. Если тип первого операнда не соответствует ни одному из допустимых типов, то в зависимости от ситуации может производиться преобразование типов или возбуждаться состояние ошибки выполнения.

Операция

Описание действия

Сложение определено для следующих типов операндов

Число + Число

Дата + Число (к дате прибавляется число секунд)

Вычитание определено для следующих типов операндов

ЧислоЧисло

ДатаЧисло (от даты отнимается число секунд)

ДатаДата (результатом является разница между двумя датами, измеренная в секундах)

Умножение

Число * Число

Деление

Число / Число

Остаток от деления

Число % Число

При выполнении арифметических операций с типом Дата следует помнить, что результат может иметь точность до 4 знаков после запятой (точность времени ‑ сотни микросекунд). Однако, при выполнении операции записи такого значения в базу данных (в реквизите соответствующего типа), дробная часть числа будет отброшена. В связи с этим рекомендуется округлять до целого значение типа Число при выполнении арифметических операций со значением типа Дата.

4.5.2. Операция конкатенации

Операция конкатенации («+») используется для того, чтобы присоединить одну строку к другой. Длина результирующей строки равна сумме длин соединяемых строк. В случае несовпадения типа данных второго или последующих операндов со строковым типом их значение преобразуется к строковому типу в соответствии с правилами преобразования типов.

Копировать в буфер обмена
ФИО = Фамилия + " " + Имя + " " + Отчество;

4.5.3. Логические операции

Логическая операция сравнивает операнды и вырабатывает значение типа Булево: Истина или Ложь. Существует два вида логических операций: операции сравнения и булевы операции. В операциях сравнения сравниваются два значения. Булевы операции выполняются над значениями типа Булево, реализуя булеву алгебру. Символы булевых операций могут комбинироваться, образуя составные операции.

Операции сравнения:

В языке определены следующие виды операций сравнения.

Операция

Выражение операции

Больше

Оп1 > Оп2

Больше или равно

Оп1 >= Оп2

Равно

Оп1 = Оп2

Не равно

Оп1 <> Оп2

Меньше

Оп1 < Оп2

Меньше или равно

Оп1 <= Оп2

Операции сравнения определены для следующих типов операндов.

Операция

Выражение операции

Больше

Число > Число

Число > Булево

Строка > Строка

Дата > Дата

Больше или равно

Число >= Число

Число >= Булево

Строка >= Строка

Дата >= Дата

Меньше

Число < Число

Число < Булево

Строка < Строка

Дата < Дата

Меньше или равно

Число <= Число

Число <= Булево

Строка <= Строка

Дата <= Дата

Равно

Любой тип = Любой тип

Не равно

Любой тип <> Любой тип

Если сравниваются значения типа Число и Булево, то значение типа Булево приводится к типу Число по следующим правилам:

● значение Истина приводится к значению 1;

● значение Ложь приводится к значению 0.

Далее выполняется сравнение значений типа Число.

Булевы операции:

В языке определены следующие виды булевых операций.

И (And)

конъюнкция (булево И)

Или (Or)

дизъюнкция (булево Или)

Не (Not)

логическое отрицание (булево отрицание Не)

Логические выражения вычисляются слева направо. Для того чтобы избежать неоднозначности и управлять последовательностью операндов, следует применять круглые скобки.

Уровни старшинства логических операций:

Уровень 1

операнды, заключенные в скобки

Уровень 2

Не

Уровень 3

И

Уровень 4

Или

Примечание. При вычислении логического выражения вычисляются только необходимые части выражения. Например, в выражении (Цена > 0) И ПроверкаСуммы(), если Цена <= 0, функция ПроверкаСуммы() не вызывается.

4.5.4. Приоритеты вычисления выражений встроенного языка

В следующей таблице представлен список операторов встроенного языка в порядке увеличения приоритета. Операторы с одинаковым приоритетом вычисляются слева направо.

Операция

Описание

Or/Или

Логическое сложение

And/И

Логическое умножение

Not/Не

Логическое отрицание

<, <=, =, >=, >, <>

Сравнение

+, ‑

Сложение, вычитание

*, /, %

Умножение, деление

-,+

Унарные плюс и минус

., ()

Разыменование, вызов метода и т. п.

Для того чтобы избежать неоднозначности и управлять последовательностью операндов, следует применять круглые скобки.

4.6. Операторы и синтаксические конструкции

4.6.1. Объявление переменной

Описание:

Позволяет в явном виде объявить переменную.

Синтаксис:

Перем <Имя переменной 1> [Экспорт] [, <Имя переменной 2>, …];

Англоязычный синтаксис:

Var <Имя переменной 1> [Export] [, <Имя переменной 2>, …];

Параметры:

<Имя переменной 1>[, <Имя переменной 2>, …]

Задается имя или имена объявляемых переменных.

Экспорт

Необязательное ключевое слово. Указывает, что данная переменная доступна при обращении к контексту этого модуля из других модулей. Данное ключевое слово необходимо указывать для каждой объявляемой переменной отдельно. Не имеет смысла при объявлении переменных отдельных процедур или функций.

Пример:

Копировать в буфер обмена
// Пример объявления одной переменной
Перем А Экспорт;
Перем Б;
// Пример объявления нескольких переменных одним оператором
Перем А, Б Экспорт;

Неявное объявление переменных:

В языке необязательно объявлять переменные в явном виде. Неявным определением переменной является первое ее появление в левой части оператора присваивания. Тип переменной определяется типом присвоенного ей значения. Не допускается использование в выражениях переменных, не объявленных ранее в явном или неявном виде.

Область использования переменной:

Область использования переменных зависит от места их определения в конфигурации. Существует три области, в которых можно объявить переменные:

● В разделе определения переменных программного модуля управляемого приложения. Это глобальные переменные.

● В разделе определения переменных модуля. Это переменные модуля.

● В процедуре или функции. Это локальные переменные.

Глобальные переменные, объявленные с ключевым словом Экспорт, доступны для использования в исполняемых операторах, выражениях, в любой процедуре и функции любого клиентского программного модуля конфигурации.

Переменные модуля доступны для использования в исполняемых операторах, выражениях, в любой процедуре и функции того программного модуля, в пределах которого они объявлены. Если они объявлены с ключевым словом Экспорт, то они доступны из других модулей через контекст модуля, в котором они объявлены.

Локальные переменные доступны в пределах той процедуры или функции, в которой они объявлены.

Если переменная определена как глобальная, то она видна из всех процедур и функций любого клиентского программного модуля конфигурации. Если же переменная определена внутри процедуры, то ее областью видимости является данная процедура или функция.

Таким образом, если две переменные с одинаковыми именами используются в двух различных процедурах модуля и имя этой переменной не упоминается как глобальное, то это две различные переменные, локальные для процедур. Если же переменная определена как глобальная переменная, то любое использование имени этой переменной будет приводить к обращению к одной и той же переменной.

Единственный способ создать для процедуры локальную переменную с именем, совпадающим с именем переменной, определенной как глобальная, ‑ это объявить ее явно при помощи оператора Перем.

4.6.2. Создание нового объекта

Описание:

Оператор позволяет создать значение указанного типа. Допустим только для тех типов, для которых разрешено создание новых значений. Для прикладных объектов необходимо использовать функциональную форму оператора Новый (вариант 2), так как при проверке модулей в конфигураторе не определены типы для прикладных объектов.

При работе с функциональной формой оператора Новый следует помнить, что операция разыменования непосредственно к результату работы оператора не может быть применена. Вначале следует присвоить результат работы оператора Новый какой-либо переменной, а затем использовать уже эту переменную.

Синтаксис (вариант 1):

Новый <Имя типа>[(<Парам 1>, ..., <Парам N>)]

Параметры:

Имя типа

Указывается имя типа, значение которого создается.

<Парам 1>, ..., <Парам N>

После имени типа в скобках могут указываться параметры, если они определены в конструкторах для данного типа. Допустимое количество параметров и их назначение указываются в описании конструкторов объекта.

Пример:

Копировать в буфер обмена
// Пример создания массива из трех элементов.
Массив = Новый Массив(3);

Синтаксис (вариант 2):

Новый (<Тип>[, <Параметры конструктора>])

Параметры:

Тип

Имя типа или значение типа Тип.

<Параметры конструктора>

Массив параметров конструктора.

Пример:

Копировать в буфер обмена
ТипЗначения = Тип("КвалификаторыСтроки");
Параметры = Новый Массив(2);
Параметры[0] = 20;
Параметры[1] = ДопустимаяДлина.Переменная;
КвалифСтр = Новый(ТипЗначения, Параметры);

4.6.3. Процедура

Описание:

Ключевое слово Процедура начинает секцию исходного текста, выполнение которого можно инициировать из любой точки программного модуля, просто указав ИмяПроцедуры() со списком параметров (если параметры не передаются, то круглые скобки, тем не менее, обязательны). Если в модуле приложения или общем программном модуле в теле описания процедуры использовано ключевое слово Экспорт, то это означает, что данная процедура является доступной из всех других программных модулей конфигурации.

При выполнении оператора Возврат процедура заканчивается и возвращает управление в точку вызова. Если в тексте процедуры не встретился оператор Возврат, то после выполнения последнего исполняемого оператора происходит выполнение неявного оператора Возврат. Конец программной секции процедуры определяется по оператору КонецПроцедуры.

Переменные, объявленные в теле процедуры в разделе Объявления локальных переменных, являются локальными переменными данной процедуры, поэтому доступны только в этой процедуре (за исключением случая передачи их как параметров при вызове других процедур, функций или методов).

Примечание. Ключевые слова Процедура, КонецПроцедуры являются не операторами, а операторными скобками, поэтому не должны заканчиваться точкой с запятой (это может приводить к ошибкам выполнения модуля).

Синтаксис:

[Асинх ]Процедура <ИмяПроцедуры>([[Знач] <Парам 1> [=<ДефЗнач>], ... ,[Знач] <Парам N> [=<ДефЗнач>]])[Экспорт]

// Объявления локальных переменных;

// Операторы;

...

[Возврат;]

// Операторы;

...

КонецПроцедуры

Англоязычный синтаксис:

[Async ]Procedure <ИмяПроцедуры>([[Val] <Парам 1> [=<ДефЗнач>], ... ,[Val] <Парам N>[=<ДефЗнач>]])[Export]

// Объявления локальных переменных;

// Операторы;

...

[Return;]

// Операторы;

...

EndProcedure

Параметры:

<ИмяПроцедуры>

Назначает имя процедуры.

Асинх

Означает, что описывается асинхронная процедура, в которой допустимо использование оператора Ждать. Доступно только при описании клиентских процедур (в том числе и обработчиков клиентских событий). Подробнее про использование асинхронных методов и оператор Ждать см. здесь.

Знач

Необязательное ключевое слово, которое указывает на то, что следующий за ним параметр передается по значению, т. е. изменение значения формального параметра при выполнении процедуры никак не повлияет на фактический параметр, переданный при вызове процедуры. Если это ключевое слово не указано, то параметр процедуры передается по ссылке, то есть изменение внутри процедуры значения формального параметра приведет к изменению значения соответствующего фактического параметра.

Если описывается асинхронная процедура ‑ ключевое слово Знач игнорируется (если указано). Параметры асинхронных методов всегда передаются по значению. Подробнее про особенность асинхронных методов см. здесь.

<Парам 1>, ..., <Парам N>

Необязательный список формальных параметров, разделяемых запятыми. Значения формальных параметров должны соответствовать значениям передаваемых при вызове процедуры фактических параметров. В этом списке определяются имена каждого из параметров так, как они используются в тексте процедуры. Список формальных параметров может быть пуст.

=<ДефЗнач>

Необязательная установка значения параметра по умолчанию. Параметры с установленными значениями по умолчанию можно располагать в любом месте списка формальных параметров (подробнее см. раздел «Передача параметров процедур и функций»).

Экспорт

Необязательное ключевое слово, которое указывает на то, что данная процедура является доступной из других программных модулей.

// Объявления локальных переменных

Объявляются локальные переменные, на которые можно ссылаться только в рамках этой процедуры (см. оператор Перем).

// Операторы

Исполняемые операторы процедуры.

Возврат

Необязательное ключевое слово, которое завершает выполнение процедуры и осуществляет возврат в точку программы, из которой было обращение к процедуре. Использование данного оператора в процедуре необязательно.

КонецПроцедуры

Обязательное ключевое слово, обозначающее конец исходного текста процедуры, завершение выполнения процедуры. Возврат в точку, из которой было обращение к процедуре.

Пример:

Копировать в буфер обмена
Перем Глоб;
// Описание процедуры
Процедура МояПроцедура(Пар1, Пар2, Пар3) Экспорт
    Глоб = Глоб + Пар1 + Пар2 + Пар3;
    Возврат;
КонецПроцедуры
Глоб = 123;
МояПроцедура(5, 6, 7); // Вызов процедуры

4.6.4. Функция

Описание:

Ключевое слово Функция начинает секцию исходного текста функции, выполнение которой можно инициировать из любой точки программного модуля, просто указав ИмяФункции со списком параметров (если параметры не передаются, то круглые скобки, тем не менее, обязательны). Если в модуле приложения или общем программном модуле в теле описания функции использовано ключевое слово Экспорт, то это означает, что данная функция является доступной из всех других программных модулей конфигурации.

Выполнение функции заканчивается оператором Возврат. Функции отличаются от процедур только тем, что возвращают ВозвращаемоеЗначение. Конец программной секции функции определяется по оператору КонецФункции.

Вызов любой функции в тексте программного модуля можно записывать как вызов процедуры, т. е. в языке допускается не принимать от функции возвращаемое значение.

Если ключевое слово Возврат в теле функции не указано или строка модуля, его содержащая, не выполнена, то функция возвращает значение типа Неопределено.

Переменные, объявленные в теле функции в разделе Объявления локальных переменных, являются локальными переменными данной функции, поэтому доступны только в этой функции (за исключением случая передачи их как параметров при вызове других процедур, функций или методов).

Примечание. Ключевые слова Функция, КонецФункции являются не операторами, а операторными скобками, поэтому не должны заканчиваться точкой с запятой (это может приводить к ошибкам выполнения модуля).

Синтаксис:

[Асинх ]Функция <ИмяФункции>([[Знач] <Парам 1>[=<ДефЗнач>], ... ,[Знач] <Парам N>[=<ДефЗнач>]])[Экспорт]

// Объявления локальных переменных;

// Операторы;

...

Возврат <Возвращаемое значение>;

// Операторы;

...

КонецФункции

Англоязычный синтаксис:

[Async ]Function <ИмяФункции>([[Val] <Парам 1>[=<ДефЗнач>], ... ,[Val] <Парам N>[=<ДефЗнач>]])[Export]

// Объявления локальных переменных;

// Операторы;

...

Return <Возвращаемое значение>;

// Операторы;

...

EndFunction

Параметры:

<ИмяФункции>

Назначает имя функции.

Асинх

Означает, что описывается асинхронная функция, в которой допустимо использование оператора Ждать. Доступно только при описании клиентских функций. Асинхронная функция всегда возвращает в качестве результата работы объект типа Обещание (вне зависимости от фактического типа возвращаемого значения). Выполнение обещания (получение фактического результата работы функции) выполняется с помощью оператора Ждать. Подробнее про использование асинхронных методов и оператор Ждать см. здесь.

Знач

Необязательное ключевое слово, которое указывает на то, что следующий за ним параметр передается по значению, т. е. изменение значения формального параметра при выполнении функции никак не повлияет на фактический параметр, переданный при вызове функции. Если это ключевое слово не указано, то параметр функции передается по ссылке, то есть изменение внутри функции значения формального параметра приведет к изменению значения соответствующего фактического параметра.

Если описывается асинхронная функция ‑ ключевое слово Знач игнорируется (если указано). Параметры асинхронных методов всегда передаются по значению. Подробнее про особенность асинхронных методов см. здесь.

<Парам 1>, ..., <Парам N>

Необязательный список формальных параметров, разделяемых запятыми. Значения формальных параметров должны соответствовать значениям передаваемых при вызове функции фактических параметров. В этом списке определяются имена каждого из параметров так, как они используются в тексте функции. Список формальных параметров может быть пуст.

=<ДефЗнач>

Необязательная установка значения параметра по умолчанию. Параметры с установленными значениями по умолчанию можно располагать в любом месте списка формальных параметров (подробнее см. раздел «Передача параметров процедур и функций»).

Экспорт

Необязательное ключевое слово, которое указывает на то, что данная функция является доступной из других программных модулей.

// Объявления локальных переменных

Объявляются локальные переменные, на которые можно ссылаться только в рамках этой функции (см. оператор Перем).

// Операторы

Исполняемые операторы функции.

Возврат <Возвращаемое значение>

Ключевое слово, которое завершает выполнение функции и возвращает указанное значение в выражение, в котором используется функция.

В качестве возвращаемого значения может выступать выражение или переменная, значение которого содержит результат обращения к функции.

КонецФункции

Ключевое слово, обозначающее конец исходного текста функции.

Пример:

Копировать в буфер обмена
Перем Глоб;
// Описание функции
Функция МояФункция(Пар1, Пар2, Пар3) Экспорт
    Глоб = Глоб + Пар1 + Пар2 + Пар3;
    Возврат Глоб;
КонецФункции
Глоб = 123;
Рез = МояФункция(5, 6, 7); // Вызов функции

4.6.5. Условные операторы

4.6.5.1. Оператор «Если»

Описание:

Оператор Если управляет выполнением программы, основываясь на результаты одного или более логических выражений. Оператор может содержать любое количество групп операторов, возглавляемых конструкциями ИначеЕслиТогда.

Синтаксис:

Если <Логическое выражение> Тогда

// Операторы

[ИначеЕсли <Логическое выражение> Тогда]

// Операторы

[Иначе]

// Операторы

КонецЕсли;

Англоязычный синтаксис:

If <Логическое выражение> Then

// Операторы

[ElsIf <Логическое выражение> Then]

// Операторы

[Else]

// Операторы

EndIf;

Параметры:

<Логическое выражение>

Логическое выражение.

Тогда

Операторы, следующие за Тогда, выполняются, если результатом логического выражения является значение Истина.

// Операторы

Исполняемый оператор или последовательность таких операторов.

ИначеЕсли

Логическое выражение, следующее за ключевым словом ИначеЕсли, вычисляется только тогда, когда условия в Если и всех предшествующих ИначеЕсли оказались равны Ложь. Операторы, следующие за конструкцией ИначеЕслиТогда, выполняются, если результат логического выражения в данном ИначеЕсли равен Истина.

Иначе

Операторы, следующие за ключевым словом Иначе, выполняются, если результаты логических выражений в конструкции Если и всех предшествующих конструкциях ИначеЕсли оказались равны Ложь.

КонецЕсли

Ключевое слово, которое завершает структуру оператора условного выполнения.

Пример:

Копировать в буфер обмена
Если ДеньНедели(ТекущаяДата()) = 6 Тогда
    Сообщить("Сегодня суббота.");
ИначеЕсли ДеньНедели(ТекущаяДата()) = 7 Тогда
    Сообщить("Сегодня воскресенье.");
Иначе
    Сообщить("Сегодня рабочий день.");
КонецЕсли;

4.6.5.2. Вычислить выражение по условию

Описание:

Позволяет вычислить одно из двух заданных выражений в зависимости от результата вычисления логического выражения.

Синтаксис:

?(<Логическое выражение>, <Выражение 1>, <Выражение 2>)

Параметры:

<Логическое выражение>

Логическое выражение, результат вычисления которого определяет одно из результирующих выражений, которые будут вычислены. Если результат его вычисления Истина, то будет вычисляться <Выражение 1>. Если результат Ложь, то <Выражение 2>.

<Выражение 1>

Результирующее выражение, которое будет вычисляться, если результат логического выражения Истина.

<Выражение 2>

Результирующее выражение, которое будет вычисляться, если результат логического выражения Ложь.

Возвращаемое значение:

Результат вычисления одного из результирующих выражений.

Пример:

Копировать в буфер обмена
Статус = ?(ПолучитьСкидку() > 10, "Особый клиент", "Обычный клиент");
Предупреждение(Статус);

4.6.6. Циклы

4.6.6.1. Цикл «Для»

Описание:

Оператор цикла Для предназначен для циклического повторения операторов, находящихся внутри конструкции ЦиклКонецЦикла. Перед началом выполнения цикла значение <Выражение 1> присваивается переменной <Имя переменной>. Значение <Имя переменной> автоматически увеличивается при каждом проходе цикла. Величина приращения счетчика при каждом выполнении цикла равна 1. Цикл выполняется, пока значение переменной <Имя переменной> меньше или равно значению <Выражение 2>. Условие выполнения цикла всегда проверяется вначале, перед выполнением цикла.

Синтаксис:

Для <Имя переменной> = <Выражение 1> По <Выражение 2> Цикл

// Операторы

[Прервать;]

// Операторы

[Продолжить;]

// Операторы

КонецЦикла;

Англоязычный синтаксис:

For <Имя переменной> = <Выражение 1> To <Выражение 2> Do

// Операторы

[Break;]

// Операторы

[Continue;]

// Операторы

EndDo;

Параметры:

<Имя переменной>

Идентификатор переменной (счетчика цикла), значение которой автоматически увеличивается на 1 при каждом повторении цикла. Так называемый счетчик цикла.

<Выражение 1>

Числовое выражение, которое задает начальное значение, присваиваемое счетчику цикла при первом проходе цикла.

По

Синтаксическая связка для параметра <Выражение 2>.

<Выражение 2>

Максимальное значение счетчика цикла. Когда переменная <Имя переменной> становится больше чем <Выражение 2>, выполнение оператора цикла Для прекращается.

Цикл

Операторы, следующие за ключевым словом Цикл, выполняются, пока значение переменной <Имя переменной> меньше или равно значению <Выражение 2>.

// Операторы

Исполняемый оператор или последовательность таких операторов.

Прервать

Позволяет прервать выполнение цикла в любой точке. После выполнения этого оператора управление передается оператору, следующему за ключевым словом КонецЦикла.

Продолжить

Немедленно передает управление в начало цикла, где производится вычисление и проверка условий выполнения цикла. Операторы, следующие в теле цикла за ним, на данной итерации обхода не выполняются.

КонецЦикла

Ключевое слово, которое завершает структуру оператора цикла.

Пример:

Копировать в буфер обмена
// Перебор дней текущего месяца
ПоследнийДеньМесяца = День(КонецМесяца(ТекущаяДата()));
Для ТекДень = 1 по ПоследнийДеньМесяца Цикл
    Состояние("Обрабатывается день: "+ ТекДень);
    // Операторы обработки очередного дня месяца
    // . . .
КонецЦикла;

4.6.6.2. Цикл обход коллекции

Описание:

Оператор цикла Для каждого предназначен для циклического обхода коллекций значений. При каждой итерации цикла возвращается новый элемент коллекции. Обход осуществляется до тех пор, пока не будут перебраны все элементы коллекции, или может быть завершен досрочно при выполнении оператора Прервать.

Синтаксис:

Для каждого <Имя переменной 1> Из <Имя переменной 2> Цикл

// Операторы

[Прервать;]

// Операторы

[Продолжить;]

// Операторы

КонецЦикла

Англоязычный синтаксис:

For each <Имя переменной 1> In <Имя переменной 2> Do

// Операторы

[Break;]

// Операторы

[Continue;]

// Операторы

EndDo;

Параметры:

<Имя переменной 1>

Переменная, которой при каждом повторении цикла присваивается значение очередного элемента коллекции.

Из

Синтаксическая связка для параметра <Имя переменной 2>.

<Имя переменной 2>

Переменная или выражение, предоставляющее коллекцию. Элементы этой коллекции будут присваиваться параметру <Имя переменной 1>.

Цикл

Операторы, следующие за ключевым словом Цикл, выполняются до тех пор, пока не будут перебраны все элементы коллекции.

// Операторы

Исполняемый оператор или последовательность таких операторов.

Прервать

Позволяет прервать выполнение цикла в любой точке. После выполнения этого оператора управление передается оператору, следующему за ключевым словом КонецЦикла.

Продолжить

Немедленно передает управление в начало цикла, где производится вычисление и проверка условий выполнения цикла. Операторы, следующие в теле цикла за ним, на данной итерации обхода не выполняются.

КонецЦикла

Ключевое слово, которое завершает структуру оператора цикла.

Пример:

Копировать в буфер обмена
// Перебор строк табличной части документа.
Документ = Документы.РасходнаяНакладная.НайтиПоКоду(12345);
// Проверим, найден нужный нам документ или нет
Если Не Документ.Пустая() Тогда
    Для каждого СтрокаСостава из Документ.Состав Цикл
   Состояние("Строка: " + Документ.Состав.Индекс(СтрокаСостава)+1);
   // Операторы обработки очередной строки табличной части
   ...
    КонецЦикла;
КонецЕсли;

4.6.6.3. Цикл «Пока»

Описание:

Оператор цикла Пока предназначен для циклического повторения операторов, находящихся внутри конструкции ЦиклКонецЦикла. Цикл выполняется, пока логическое выражение равно Истина. Условие выполнения цикла всегда проверяется вначале, перед выполнением цикла.

Синтаксис:

Пока <Логическое выражение> Цикл

// Операторы

[Прервать;]

// Операторы

[Продолжить;]

// Операторы

КонецЦикла

Англоязычный синтаксис:

While <Логическое выражение> Do

// Операторы

[Break;]

// Операторы

[Continue;]

// Операторы

EndDo;

Параметры:

<Логическое выражение>

Логическое выражение.

Цикл

Операторы, следующие за ключевым словом Цикл, выполняются, пока результат логического выражения равен Истина.

// Операторы

Исполняемый оператор или последовательность таких операторов.

Прервать

Позволяет прервать выполнение цикла в любой точке. После выполнения этого оператора управление передается оператору, следующему за ключевым словом КонецЦикла.

Продолжить

Немедленно передает управление в начало цикла, где производится вычисление и проверка условий выполнения цикла. Операторы, следующие в теле цикла за ним, на данной итерации обхода не выполняются.

КонецЦикла

Ключевое слово, которое завершает структуру оператора цикла.

Пример:

Копировать в буфер обмена
ВыборкаДок = Документы.РасходнаяНакладная.Выбрать();
// Цикл по всем документам
Пока ВыборкаДок.Следующий() Цикл
    // Отобразим Документ в панели состояния
    Состояние("Обрабатывается документ №" + ВыборкаДок.Номер);
    // Операторы выполнения действий над документом
КонецЦикла;

4.6.7. Безусловный переход

Описание:

Безусловная передача управления на другой оператор программы. Передает управление от одного оператора к другому.

Область действия оператора ограничивается программным модулем, процедурой или функцией; он не может передать управление за пределы программного модуля, процедуры или функции.

Примечание 1. Метка в этом операторе не должна быть меткой перехода на оператор Процедура или Функция.

Примечание 2. Оператор безусловного перехода не может быть использован для передачи управления на операторы, находящиеся внутри конструкций: ПокаКонецЦикла, ДляКонецЦикла, Для каждогоКонецЦикла, ЕслиКонецЕсли, ПопыткаИсключениеКонецПопытки извне этих конструкций.

Синтаксис:

Перейти <Метка>;

Пример:

Копировать в буфер обмена
Перейти ~Метка1;
...
~Метка1: Сообщить("Осуществлен переход по метке.");

4.6.8. Выполнение фрагмента кода

Описание:

Позволяет выполнить фрагмент кода, который передается ему в качестве строкового значения.

ВНИМАНИЕ! Не рекомендуется реализовывать с помощью этого метода существенную часть функциональности прикладных решений.

Примечание. Исполняемый код не может содержать в себе отдельных процедур или функций, т. к. исполнение кода само по себе идет в рамках процедуры или функции, в которой использован этот оператор. А также не может содержать явного объявления переменных.

Синтаксис:

Выполнить(<Строка>)

Англоязычный синтаксис:

Execute(<Строка>)

Параметры:

<Строка>

Строка, содержащая текст исполняемого кода.

Пример:

Копировать в буфер обмена
// Выводит в окно сообщений текущую дату
Выполнить("Сообщить(ТекущаяДата())");

4.6.9. Ожидание завершения асинхронной функции

Описание:

Оператор Ждать ожидает завершение выполнения асинхронной функции встроенного языка. На время ожидания исполнение текущего метода прерывается, а управление передается вызывающему коду. В то же время, элемент стека вызовов встроенного языка, соответствующий приостановленному методу, не очищается и не удаляется. После завершения ожидания исполнение возобновляется с той же точки, где оно было приостановлено. Кроме того, восстанавливается окружение, которое было на момент приостановки выполнения, включая значения локальных переменных.

Таким образом, выполнение оператора Ждать выглядит следующим образом:

● Выполнение метода приостанавливается.

● При первой приостановке управление будет возвращено коду, который изначально вызвал текущий метод. При последующих приостановках управление будет возвращено системному коду, вызвавшему возобновление выполнения.

● Возобновление происходит, как только Обещание будет завершено. При этом оператор Ждать возвращает значение или генерирует исключение.

Синтаксис:

[Назначение = ]Ждать <Обещание>;

Англоязычный синтаксис:

[Destination = ]Await <Promise>;

Параметры:

Обещание

Значение типа Обещание. Данное значение является объектом, который возвращает асинхронная функция системы «1С:Предприятие».

Возвращаемое значение:

Возвращаемое значение асинхронной функции ‑ в случае успешного завершения работы асинхронной функции. Исключение ‑ если во время работы асинхронной функции возникло исключение.

Пример:

Копировать в буфер обмена
СписокФайлов = Ждать НайтиФайлыАсинх(Ждать КаталогВременныхФайловАсинх(), МаскаВсеФайлы(), Ложь);

Смотри также:

● Асинхронность через обещания (см. здесь).

4.6.10. Исключения и работа с ними

4.6.10.1. Общая информация

Во время работы клиентского приложения возникают ошибки. Они могут быть вызваны разными причинами: ошибками в данных, ошибками в алгоритмах, проблемы в стороннем программном обеспечении (например, ошибка СУБД), проблемами с физическим окружением (например, с сетью). Для ошибок может применяться и другое название ‑ исключение. Термины «исключение» и «ошибка» могут употребляться как синонимы, но это зависит от контекста использования термина.

Система программ «1С:Предприятие» позволяет:

● Генерировать исключение из текста на встроенном языке с помощью оператора ВызватьИсключение.

● Перехватывать ошибки (при необходимости и возможности). Это делается с помощью оператора Попытка … Исключение.

● Получать информацию о произошедшей ошибке, анализировать стек исключений, и получать принадлежность исключения к какой-либо категории из списка.

● Настраивать тексты сообщений об ошибках и формировать отчеты об ошибках.

● Перехватывать любые сообщения об ошибках в целях отображения информации об ошибке и формирования отчета об ошибке.

В данном разделе будут рассмотрены возможности системы «1С:Предприятие» по генерации исключения и перехвату исключений. Описание инструментов обработки информации об ошибке (в том числе настройка представления ошибки) см. здесь.

4.6.10.2. Вызвать исключение

Описание:

При использовании данного оператора вызывается новое исключение. Оператор может иметь два варианта синтаксиса: с одним (вариант синтаксиса 1) или несколькими параметрами (вариант синтаксиса 2). Если необходимо указать более одного параметра, то следует использовать функциональную форму оператора.

Вариант синтаксиса 1:

ВызватьИсключение <Выражение>

Англоязычный вариант синтаксиса 1:

Raise <Expression>

Параметры:

<Выражение>

Результат вычисления выражения преобразуется к строке, и данная строка используется в качестве описания исключения.

Пример:

Копировать в буфер обмена
ВызватьИсключение "Документ не может быть проведен";

Вариант синтаксиса 2:

ВызватьИсключение(<Выражение>, <Категория>, <Код>, <ДополнительнаяПричина>, <Причина>)

Англоязычный вариант синтаксиса 2:

Raise(<Expression>, <Category>, <Code>, <AdditionalCause>, <Cause>)

Параметры:

<Выражение>

Результат вычисления выражения преобразуется к строке, и данная строка используется в качестве описания исключения.

<Категория>­необязательный

Указывается категория ошибки, к которой будет принадлежать формируемое исключение. Категория будет использоваться для отображения пользователю. Значением данного параметра может быть только значение системного перечисления КатегорияОшибки. Недопустимо использование следующих категория ошибок: ВсеОшибки, ПрочаяОшибка, ОшибкаКомпиляцииВстроенногоЯзыка, ОшибкаВоВремяВыполненияВстроенногоЯзыка, ИсключениеВызванноеИзВстроенногоЯзыка. Исключение, сформированное с помощью функциональной формы оператора ВызватьИсключение, кроме категории, указанной в данном параметре, будет принадлежать категориям ОшибкаВоВремяВыполненияВстроенногоЯзыка и ИсключениеВызванноеИзВстроенногоЯзыка.

При формировании исключения из программы на встроенном языке, желательно указывать категорию формируемого исключения. Указанная категория должна соответствовать формируемой ошибке. Отображение ошибки зависит от ее категории, поэтому корректное указание категории поможет пользователю лучше понять случившееся и причину проблемы.

<Код>­необязательный

Произвольное значение типа Строка, которое может использоваться в обработчиках ошибок для классификации исключений. Правила формирования кода ошибки и принципы кодификации относятся к компетенции прикладных разработчиков.

<ДополнительнаяПричина>­необязательный

Значение типа Строка, которая представляет собой дополнительную информацию о формируемой ошибке.

<Причина>­необязательный

В том случае, когда формируемая ошибка возникла по причине какого-либо другого исключения, то следует описание этого исключения указать в данном параметре. Значение имеет тип ИнформацияОбОшибке.

Пример:

Копировать в буфер обмена
ВызватьИсключение ("Документ не может быть проведен", КатегорияОшибки.ОшибкаКонфигурации, "ERR.DOCS.0001", "Клиенту запрещена отгрузка");

4.6.10.3. Обработка исключения

Описание:

Оператор Попытка управляет выполнением программы, основываясь на возникающих при выполнении модуля ошибочных (исключительных) ситуациях, и определяет обработку этих ситуаций.

В качестве ошибочных (исключительных) ситуаций воспринимаются ошибки времени выполнения модуля. Не предусмотрено определяемых пользователем исключений.

Если при выполнении последовательности операторов попытки произошла ошибка времени выполнения, то выполнение оператора, вызвавшего ошибку, прерывается и управление передается на первый оператор последовательности операторов исключения. При этом управление будет передано даже в том случае, если ошибку вызвал оператор, находящийся в процедуре или функции, вызванной из операторов попытки. Если ошибка произошла в вызванной процедуре или функции, то ее выполнение будет прервано, а локальные переменные ‑ уничтожены. Это справедливо для любой вложенности вызовов. После выполнения последовательности операторов исключения управление передается на следующий за ключевым словом КонецПопытки оператор. Если же последовательность операторов попытки выполнилась без ошибок, то последовательность операторов исключения будет пропущена и управление также будет продолжено с оператора, следующего за ключевым словом КонецПопытки.

Конструкции ПопыткаИсключениеКонецПопытки могут быть вложенными. При этом при возникновении исключительной ситуации управление передается на тот обработчик, в попытке которого произошла ошибка. Если же в последовательности операторов исключения этого обработчика выполняется оператор ВызватьИсключение, выполнение передается вышестоящему обработчику исключения и так далее. Если вышестоящего обработчика нет, исключительная ситуация обрабатывается системно с прекращением выполнения программного модуля.

В выдаче диагностики помощь могут оказать встроенные функции ОписаниеОшибки() и ИнформацияОбОшибке() (см. описание функций встроенного языка). Также следует учитывать, что попадание во вложенный обработчик исключения приводит к тому, что информация о «родительском» исключении теряется.

С помощью конструкции ПопыткаИсключениеКонецПопытки не могут быть перехвачены следующие ошибки:

● Ошибки компиляции модулей встроенного языка во время исполнения.

● Ошибки времени исполнения, возникающие в обработчиках ПередЗакрытием() и ПриЗакрытии() управляемой формы.

Такие ошибки всегда будет отображаться системой «1С:Предприятие» и приводить к прекращению выполнения встроенного языка.

Синтаксис:

Попытка

// Операторы попытки

Исключение

// Операторы исключения

[ВызватьИсключение;]

// Операторы исключения

КонецПопытки;

Англоязычный синтаксис:

Try

// Операторы попытки

Except

// Операторы исключения

[Raise;]

// Операторы исключения

EndTry;

Параметры:

// Операторы попытки

Исполняемый оператор или последовательность таких операторов.

Исключение

Операторы, следующие за ключевым словом Исключение, выполняются, если при выполнении последовательности операторов произошла ошибка времени выполнения.

// Операторы исключения

Исполняемый оператор или последовательность операторов, которые обрабатывают исключительную ситуацию.

ВызватьИсключение

Оператор позволяет вызвать исключение в тех случаях, когда, несмотря на отработку исключительной ситуации, необходимо прервать выполнение модуля с ошибкой времени выполнения. Оператор допустим только внутри операторных скобок ИсключениеКонецПопытки.

Выполнение данного оператора прекращает выполнение последовательности операторов исключения, и производится поиск более «внешнего» обработчика исключения (при вложенных попытках). Если таковой есть, то управление передается на его первый оператор. Если нет, то исключительная ситуация обрабатывается системно, выдается сообщение о первоначально возникшей ошибке, а выполнение модуля прекращается.

КонецПопытки

Ключевое слово, которое завершает структуру оператора обработки исключительных ситуаций.

Пример:

Копировать в буфер обмена
Процедура СформироватьВExcel()
    Попытка
   // Пытаемся обратиться к программе MS Excel
   Табл = Новый ComObject("Excel.Application");
    Исключение
   Предупреждение(ОписаниеОшибки());
   Возврат;
    КонецПопытки;
    // Операторы формирования отчета
    ...
КонецПроцедуры

4.6.11. Обработчики событий

4.6.11.1. Добавить обработчик события

Описание:

Добавляет обработчик события.

При добавлении обработчика события производится проверка соответствия числа параметров события числу параметров метода, назначаемого в качестве обработчика.

Синтаксис:

ДобавитьОбработчик <Событие>, <ОбработчикСобытия>;

Англоязычный синтаксис:

AddHandler <Событие>, <ОбработчикСобытия>;

Параметры:

<Событие>

Событие, которому добавляется обработчик.

Событие задается в форме <Выражение>.<ИмяСобытия>, где:

<Выражение> ‑ произвольное выражение на встроенном языке. Его результатом должен быть объект, к событию которого добавляется обработчик.

<ИмяСобытия> ‑ идентификатор (имя) события.

<ОбработчикСобытия>

Процедура/функция-обработчик события.

Обработчиком события может являться метод объекта встроенного языка. Тогда <ОбработчикСобытия> задается как <Выражение>.<ИмяОбработчика>, где:

<Выражение> ‑ произвольное выражение на встроенном языке. Его результатом должен быть объект, метод которого служит обработчиком события.

<ИмяОбработчика> ‑ имя метода обработчика события.

Также в качестве обработчика события может быть задана процедура/функция, находящаяся в области видимости. В этом случае обработчик события задается как имя процедуры/функции.

Имеется возможность оформлять подписку на одноименные (в COM-объектах) события, но с разным числом параметров. Для этого на встроенном языке необходимо создать несколько обработчиков (каждый с указанием уникального имени и с указанием нужного количества параметров), а механизм подписки сам выберет нужный обработчик для нужной подписки.

Пример:

Копировать в буфер обмена
Обработка = Обработки.КонтрольДокумента.Создать();
Накладная = Документы.Накладная.СоздатьДокумент();
ДобавитьОбработчик Накладная.ПриЗаписи, Обработка.ПриЗаписиДокумента;
msword = Новый COMОбъект("Word.Application");
ДобавитьОбработчик msword.DocumentChange, ПриИзмененииДокумента;
Процедура ПриИзмененииДокумента()
    Сообщить("Документ изменен");
КонецПроцедуры

Пример с разными параметрами:

Копировать в буфер обмена
// Обработчик без параметров
Процедура ОбработкаСобытия()
КонецПроцедуры
// Обработчик с одним параметром
Процедура ОбработкаСобытия2(Параметр)
КонецПроцедуры
// Объект может генерировать события как с параметром,
// так и без параметров
Объект = Новый COMОбъект("Test.Events");
ДобавитьОбработчик Объект.TestEvent, ОбработкаСобытия
ДобавитьОбработчик Объект.TestEvent, ОбработкаСобытия2

4.6.11.2. Удалить обработчик события

Описание:

Удаляет обработчик события.

При удалении обработчика события производится проверка соответствия числа параметров события числу параметров метода, назначенного в качестве обработчика.

Синтаксис:

УдалитьОбработчик <Событие>, <ОбработчикСобытия>;

Англоязычный синтаксис:

RemoveHandler <Событие>, <ОбработчикСобытия>;

Параметры:

<Событие>

Событие, обработчик которого удаляется.

Событие задается в форме <Выражение>.<ИмяСобытия>, где:

<Выражение> ‑ произвольное выражение на встроенном языке. Его результатом должен быть объект, обработчик события которого удаляется.

<ИмяСобытия> ‑ идентификатор (имя) события.

<ОбработчикСобытия>

Процедура/функция-обработчик события.

Обработчиком события может являться метод объекта встроенного языка. Тогда <ОбработчикСобытия> задается как <Выражение>.<ИмяОбработчика>, где:

<Выражение> ‑ произвольное выражение на встроенном языке. Его результатом должен быть объект, метод которого служит обработчиком события.

<ИмяОбработчика> ‑ имя метода обработчика события.

Также в качестве обработчика события может быть задана процедура/функция, находящаяся в области видимости. В этом случае обработчик события задается как имя процедуры/функции.

Пример:

Копировать в буфер обмена
УдалитьОбработчик Накладная.ПриЗаписи, Обработка.ПриЗаписиДокумента;

4.7. Основные приемы работы

4.7.1. Обращение к свойствам объектов

Помимо основного обращения через точку, в языке системы «1С:Предприятие» предусмотрен механизм обращения к свойствам объектов по строке с именем свойства с помощью оператора [] (квадратные скобки).

Свойство объекта ([])

Описание:

Такая конструкция позволяет обращаться к свойствам объектов так же, как это делается через точку с указанием имени свойства.

Синтаксис:

<Объект>[<Имя свойства>]

Параметры:

<Объект>

Объект, к свойству которого идет обращение.

<Имя свойства>

Тип Строка. Имя свойства, к которому необходимо обратиться.

Пример:

Копировать в буфер обмена
Спр = Справочники.Номенклатура.НайтиПоКоду(ИскомыйКод);
// Обращение к наименованию справочника по строке с именем свойства
A = Спр["Наименование"];
// Обращение к наименованию справочника по имени свойства
A = Спр.Наименование;
// Оба эти обращения к свойству абсолютно равнозначны

4.7.2. Дополнение контекста объектов и форм

В языке есть возможность при обращении к объектам и формам извне, из других программных модулей, обращаться к переменным, процедурам и функциям этих модулей, как к свойствам и методам самих объектов и форм. Можно обращаться к тем переменным, процедурам и функциям, которые объявлены с ключевым словом Экспорт. Для форм дополнительно возможно обращение к реквизитам формы.

Пример:

Копировать в буфер обмена
// Пример использования процедуры печати документов из журнала
// документов. Допустим, у нас есть несколько различных документов,
// причем у всех есть процедура Печать(). В модуле журнала
// документов располагается кнопка "Печать", которая
// вызывает процедуру печати текущего документа журнала.
Процедура ПечатьНажатие(Элемент)
    // Получим текущий документ, на котором установлен курсор.
    ТекДок = ЭлементыФормы.ЖурналСписок.ТекущаяСтрока;
    // Получим основную форму текущего документа.
    ФрмТекДок = ТекДок.ПолучитьФорму();
    // Вызовем процедуру печати, расположенную
    // в модуле формы документа.
    ФрмТекДок.Печать();
КонецПроцедуры

4.7.3. Сериализация/десериализация

Сериализация ‑ это процесс преобразования объекта в поток байтов для сохранения или передачи в память, в базу данных или в файл. Эта операция предназначена для того, чтобы сохранить состояния объекта для последующего воссоздания при необходимости. Обратный процесс называется десериализацией. В системе «1С:Предприятие» существует несколько различных видов сериализации/десериализации: обычная сериализация, сериализация в XML и XDTO-сериализация. XDTO-сериализация может выполняться в формат XML и JSON. Платформа для внутренних нужд всегда использует XDTO-сериализацию в формат XML. Каждая из этих сериализаций используется в различных целях.

Не для каждого объекта в системе «1С:Предприятие» реализована возможность сериализации вообще и конкретного вида сериализации в частности. При этом Синтакс-помощник отражает информацию о том, какой вид сериализации реализован для данного объекта. Если в Синтакс-помощнике нет информации о доступных видах сериализации ‑ значит объект вообще не поддерживает сериализацию.

Рассмотрим, как используется сериализация/десериализация. Например, при серверном вызове (и возврате на сторону клиентского приложения) процесс выглядит следующим образом:

● выполняется сериализация всех параметров вызова серверного метода;

● выполняется вызов метода с одновременной передачей сериализованного представления параметров на сторону сервера;

● на сервере выполняется десериализация переданных параметров;

● выполняется собственно серверный вызов;

● выполняется сериализация всех возвращаемых параметров и результата вызова (если он есть);

● выполняется возврат управления на сторону клиентского приложения с одновременной передачей сериализованных данных;

● на стороне клиентского приложения происходит десериализация результатов вызова;

● вызов завершен.

Более подробно особенности передачи параметров при клиент-серверном взаимодействии см. здесь. Но из описания процесса вызова сразу вытекает одна очень важная особенность: циклические ссылки на объекты в параметрах серверных вызовов приведут к невозможности выполнить вызов из-за того, что сериализация не будет выполнена.

Еще одной особенностью процесса сериализация/десериализация является следующий момент: если сериализуемый объект ссылается на один экземпляр каких-либо данных из разных свойств, то после десериализации объекта будет наблюдаться следующее:

● Объект, который был присвоен разным свойствам сериализуемого объекта ‑ больше не связан со свойствами десериализованного объекта.

● Свойства, которые ранее ссылались на один и тот же объект, после десериализации ссылаются на несколько разных объектов (по числу свойств, которые ранее ссылались на один объект).

Поясним сказанное примером:

Копировать в буфер обмена
&НаСервереБезКонтекста
Процедура ТестоваяНаСервере(ПараметрМетода)
    ПараметрМетода.Свойство1.Свойство1 = 5;
    ПараметрМетода.Свойство1.Свойство2 = 6;
    ПараметрМетода.Свойство2.Свойство1 = 7;
    ПараметрМетода.Свойство2.Свойство2 = 8;
КонецПроцедуры
&НаКлиенте
Процедура Тестовая(Команда)
    ВложенныйОбъект = Новый Структура("Свойство1, Свойство2", 1, 2);
    ОсновнойОбъект = Новый Структура;
    ОсновнойОбъект.Вставить("Свойство1", ВложенныйОбъект);
    ОсновнойОбъект.Вставить("Свойство2", ВложенныйОбъект);
    ТестоваяНаСервере(ОсновнойОбъект);
КонецПроцедуры

В данном примере ВложенныйОбъект ‑ это тот объект, который будет «размножен» в результате сериализации/десериализации. До вызова метода ТестоваяНаСервере() свойства ОсновнойОбъект.Свойство1 и ОсновнойОбъект.Свойство2 содержат ссылку на одну и ту же структуру ВложенныйОбъект. Более того, изменение любого свойства структуры ВложенныйОбъект автоматически приведет к тому, при обращении через «две точки» будут доступны одинаковые значения (ОсновнойОбъект.Свойство1.Свойство1 и ОсновнойОбъект.Свойство2.Свойство1).

Если посмотреть состояние структуры ОсновнойОбъект после выполнения вызова, то будет видно, что все 4 свойства структуры ОсновнойОбъект заполнены разными значениями. Более того, после вызова серверного метода попытка изменения структуры ВложенныйОбъект уже никак не влияет на состояние структуры ОсновнойОбъект.

Аналогичная информация приводится в разделе, описывающим особенность передачи параметров методов при клиент-серверном вызове.

Смотри также:

● Особенности передачи параметров при вызовах процедур и функций (см. здесь).

4.7.4. Передача параметров процедур и функций

4.7.4.1. Общая информация

Передача параметров процедур и функций выполняется двумя способами. Один способ называется передачей по ссылке и представляет собой передачу не конкретного значения параметра, а адреса памяти (ссылки на переменную), где расположено это значение. Изменение переданного значения в вызываемой процедуре или функции приведет к изменению передаваемой переменной в вызывающем методе.

Другой способ называется передачей по значению и представляет собой передачу копии значения параметра. В этом случае изменение переданного значения в вызываемой процедуре или функции не приведет к изменению значения передаваемой переменной в вызывающем методе.

В то же время механизм передачи параметров процедур и функций зависит от того, какой вызов будет выполняться:

● вызов без передачи управления между клиентом и сервером (только на клиенте или только на сервере);

● вызов с передачей управления между клиентом и сервером (в том числе и в файловом варианте информационной базы).

Но перед тем, как рассмотреть различия между способами передачи параметров, необходимо рассмотреть еще один момент, напрямую влияющий на фактическую возможность осуществления вызова с передачей управления с клиента на сервер. Этот момент включает два фактора:

● Поддержку типа значения как на клиенте, так и на сервере.

● Поддержку сериализации значения в нужном формате.

Первый фактор важен для ответа на вопрос: нужное значение может использоваться на другой стороне вызова? Например, тип ТаблицаЗначений доступен на стороне сервера, но не доступен на стороне тонкого, мобильного или веб-клиента. Это значит, что возврат значения типа ТаблицаЗначений с сервера на клиентскую сторону управляемого приложения в принципе невозможно. Для того, чтобы проверить доступность значения, следует в синтакс-помощнике посмотреть раздел Доступность для требуемого типа значения. Так, для таблицы значений в этом разделе будет следующий текст, в котором отсутствует тонкий клиент:

Копировать в буфер обмена
Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер.

В связи с тем, что для передачи значений с клиента на сервер (и обратно) используется сериализация, второй фактор описывает возможность значения некоторого типа быть переданным между клиентом и сервером. Система «1С:Предприятие» поддерживает два вида приложений: обычное и управляемое. Для обмена данными в клиент-серверном взаимодействии для разных видов приложений используется разная сериализация. Эти возможности также описаны в разделе Доступность синтакс-помощника. Для того, чтобы значение какого-либо типа могла быть передано с клиента на сервер в управляемом приложении, этот тип должен поддерживать сериализация в XDTO. Для того, чтобы значение требуемого типа могло передаваться в обычном приложении, то требуемой тип должен поддерживать возможность обмена с сервером.

Так, для типа СправочникСсылка в разделе Доступность указан следующий текст:

Копировать в буфер обмена
Возможен обмен с сервером. Сериализуется. Данный объект может быть сериализован в/из XML. Может использоваться в реквизитах управляемой формы. Данный объект может быть сериализован в/из XDTO. Тип XDTO, соответствующий данному объекту, определяется в пространстве имен {http://v8.1c.ru/8.1/data/enterprise/current-config}. Имя типа XDTO: СправочникСсылка.<Имя справочника>.

Из него видно, что значение данного тип может передаваться между клиентом и сервером как в управляемом приложении (имеется текст Данный объект может быть сериализован в/из XDTO), так и в обычном приложении (имеется текст Возможен обмен с сервером).

В тоже самое время, для типа ПользовательИнформационнойБазы в разделе Доступность указан следующий текст:

Копировать в буфер обмена
Возможен обмен с сервером.

Из этого текста видно, что в управляемом приложении передавать значения такого типа между клиентом и сервером ‑ не получится.

Смотри также:

● Варианты работы (см. здесь).

● Особенности использования типов значений в системе «1С:Предприятие» (см. здесь).

4.7.4.2. Вызов без передачи управления с клиента на сервер

Если вызов происходит без передачи управления между клиентом и сервером (вызов происходит только на клиентской или только на серверной стороне), то по умолчанию параметры передаются по ссылке. При этом изменение формального параметра ведет к изменению соответствующего фактического параметра. С помощью модификатора Знач перед именем формального параметра можно указать, что параметр передается по значению. В этом случае нельзя изменить значение фактического параметра путем присвоения формальному параметру какого-либо значения.

Копировать в буфер обмена
&НаКлиенте
Процедура МояПроцедура()
    А = 100;
    ПоСсылке(А);
    // Переменная А = 40, так как в теле процедуры значение
    // параметра Параметр1 изменено на 40.
    // Изменение переменной А произошло потому, что параметр передавался по ссылке
    А = 100;
    ПоЗначению(А);
    // Переменная А = 100, несмотря на то, что в в теле процедуры
    // значение параметра Параметр1 изменено на 40.
    // Изменение переменной А не произошло, так как параметр передавался по значению
КонецПроцедуры
&НаКлиенте
Процедура ПоСсылке(Параметр1)
    Параметр1 = 40;
КонецПроцедуры
&НаКлиенте
Процедура ПоЗначению(Знач Параметр1)
    Параметр1 = 40;
КонецПроцедуры

Однако необходимо помнить следующую особенность: если параметром передается агрегатный объект, то невозможно присвоить фактическому параметру другое значение, но возможно изменить сам переданный объект. Например, если в процедуру по значению передан массив, то можно очистить этот массив методом Очистить(), но нельзя изменить в вызывающей процедуре само значение параметра.

Копировать в буфер обмена
&НаКлиенте
Процедура МояПроцедура()
    Массив = Новый Массив;
    Массив.Добавить(12);
    Массив.Добавить(18);
    // В массиве есть два элемента
    ПоЗначению(Массив);
    // Массив пустой, но это по прежнему массив, а не Число
КонецПроцедуры
// Параметр передается по значению
&НаКлиенте
Процедура ПоЗначению(Знач Параметр)
    // В массиве два значения
    Параметр.Очистить();
    // В массиве нет значений!
    // Меняем формальный параметр
    Параметр = 14;
    // Изменено значение только формального параметра
КонецПроцедуры

Также следует учитывать особенности хранения переменных при организации вызовов:

Копировать в буфер обмена
&НаКлиенте
Процедура ТестоваяПроцедура()
    ЗначениеА = Новый Массив;
    ЗначениеА.Добавить(1);
    ЗначениеА.Добавить(2);
    ЗначениеБ = ЗначениеА;
    // обращение к любой переменной: ЗначениеА или ЗначениеБ вызывает
    // изменение одного и того же масива
    МояПроцедура(ЗначениеА, ЗначениеБ);
    // После завершения вызова процедуры обе переменные (ЗначениеА и ЗначениеБ)
    // ссылаются на один массив.
    // В массиве находятся следующие значения:
    // ЗначениеА[0] = ЗначениеБ[0] = "А"
    // ЗначениеА[1] = ЗначениеБ[1] = "Б"
КонецПроцедуры
&НаКлиенте
Процедура МояПроцедура(Параметр1, Параметр2)
    // Несмотря на то, что параметров два, фактически работа происходит с одним массивом
    Параметр1[0] = 5;
    Параметр1[1] = 6;
    Параметр2[0] = "А";
    Параметр2[1] = "Б";
КонецПроцедуры

В данном примере следует обратить внимание на тот факт, что операция присваивания ЗначениеБ = ЗначениеА; (в процедуре ТестоваяПроцедура()) не приведет к созданию копии массива, который находится в переменной ЗначениеА. Обе переменные будут ссылаться на один и тот же массив!

При этом в процедуру МояПроцедура() параметры передаются по ссылке, следовательно, при изменении двух разных формальных параметров происходит изменение одного физического массива.

4.7.4.3. Вызов с передачей управления с клиента на сервер

Вызов процедур и функций с передачей управления между клиентом и сервером характерен тем, что в общем случае при таком вызове изменяется компьютер, на котором происходит работа вызываемого метода. Это происходит потому, что (в общем случае) клиент работает на одном компьютере, а сервер ‑ на другом. Следовательно, нельзя говорить о передаче параметров по ссылке, т. к. один компьютер не может получить прямого доступа к памяти другого компьютера. При работе в файл-серверном варианте клиент и сервер представляют собой один компьютер, но на логику взаимодействия это не влияет. Поэтому передача параметров в случае клиент-серверного взаимодействия происходит особым образом:

● При передаче управления с клиента на сервер (и обратно) всегда передаются копии параметров. При вызове серверной процедуры или функции с клиента происходит создание копии фактического параметра и передача этой копии на сторону сервера. При возврате управления с сервера на клиента, также происходит создание копии формального параметра (с которым происходила работы в вызванной процедуре или функции) для передачи обратно на клиента.

● Если формальный параметр указан с модификатором Знач, то значение параметра будет передаваться только при вызове процедуры или функции и не будет передаваться обратно при возврате управления на клиента.

● Если для нескольких формальных параметров указывается одно и то же фактическое значение, то создается столько копий фактического значения, для скольких формальных параметров используется значение.

● Если в качестве формальных параметров указано значение одной и той же переменной, то после возврата управления с сервера значение этой переменной будет установлено в значение самого правого формального параметра (без модификатора Знач), который изменялся в вызываемой функции.

● Если во время исполнения серверного метода произошло исключение, то значения параметров метода, переданных по ссылке, будут неопределены при возврате на сторону клиента.

Копировать в буфер обмена
&НаКлиенте
Процедура ТестоваяПроцедура(Команда)
    ЗначениеА = Новый Массив;
    ЗначениеА.Добавить(1);
    ЗначениеА.Добавить(2);
    ЗначениеБ = ЗначениеА;
    // обращение к любой переменной: ЗначениеА или ЗначениеБ вызывает
    // изменение одного и того же масива
    // При вызове процедуры создается копия массива для каждого формального параметра
    СервернаяПроцедура(ЗначениеА, ЗначениеБ);
    // После завершения вызова процедуры:
    // 1. Переменные ЗначениеА и ЗначениеБ ссылаются на разные массивы
    // 2. В массивах находятся разные значения
    // ЗначениеА[0] = 5
    // ЗначениеА[1] = 6
    // ЗначениеБ[0] = "А"
    // ЗначениеБ[1] = "Б"
КонецПроцедуры
&НаСервере
Процедура СервернаяПроцедура(Параметр1, Параметр2)
    // Так как передаются копии, для каждого формального параметра на сервере создан "свой" массив
    Параметр1[0] = 5;
    Параметр1[1] = 6;
    Параметр2[0] = "А";
    Параметр2[1] = "Б";
    // С сервера будут возвращаться копии переменных Параметр1 и Параметр2
КонецПроцедуры

Следует всегда помнить о том, что при передаче параметров на сервер создается копия значения. Это позволит избежать труднодиагностируемых ошибок при работе системы. Рассмотрим пример:

Копировать в буфер обмена
&НаКлиенте
Процедура ТестоваяПроцедура(Команда)
    ЗначениеА = Новый Массив;
    ЗначениеА.Добавить("1");
    ЗначениеА.Добавить("2");
    ЗначениеБ = ЗначениеА;
    Структура = Новый Структура("Ключ1, Ключ2", ЗначениеА, ЗначениеБ);
    СервернаяПроцедура(Структура);
    ЗначениеА[0] = 9;
    ЗначениеА[1] = 8;
    ЗначениеБ[0] = "C";
    ЗначениеБ[1] = "D";
КонецПроцедуры
&НаСервере
Процедура СервернаяПроцедура(Параметр1)
 Параметр1.Ключ1[0] = "0";
 Параметр1.Ключ1[1] = "1";
 Параметр1.Ключ2[0] = "2";
 Параметр1.Ключ2[1] = "3";
КонецПроцедуры

После завершения вызова процедуры ТестоваяПроцедура() будет наблюдаться следующее состояние переменных:

● Массивы ЗначениеА и ЗначениеБ идентичны и содержат значения «С» в первом элементе и значение «D» во втором элементе, т. к. переменная ЗначениеБ указывает на массив из переменной ЗначениеА и значения этих переменных не передавались на сервер.

● В переменной Структура будут находиться два массива:

● Со значениями «0» и «1» для элементов массива, находящегося в элементе структуры с ключом Ключ1.

● Со значениями «2» и «3» для элементов массива, находящегося в элементе структуры с ключом Ключ2.

● Такое поведение будет обусловлено тем, что при вызове процедуры происходит создание копии не только самого параметра (переменная Структура), но и всех объектов, находящихся в этой структуре: два массива, которые изначально указывали на один массив со значениями элементов «1» и «2».

4.7.4.4. Общие особенности указания параметров

При передаче параметров в метод (процедуру или функцию) различаются две ситуации: когда параметр опущен и когда параметр пропущен. Пропущенный параметр ‑ это параметр, значение которого явным образом не указано. Если пропускается несколько параметров, то в строке с вызовом метода каждый из пропускаемых параметров должен быть отмечен «своей» разделительной запятой.

Копировать в буфер обмена
Процедура МояПроцедура(Параметр1, Параметр2)КонецПроцедуры
// Параметр Параметр1 - пропущен
МояПроцедура( ,1);

Опущенным может быть только один или несколько параметров, указанных справа в списке формальных параметрах при описании метода. При этом опускать можно только параметры, которые имеют значение по умолчанию. Если опущеными будут параметры, не имеющие значений по умолчанию, то при компиляции данного программного кода будет выдана ошибка о несоответствии числа параметров.

Значение опущенного параметра (одного или нескольких) определяется значениями по умолчанию для опускаемых параметров. Значение пропускаемого параметра равно значению по умолчанию (если таковое задано) или значению Неопределено, если для формального параметра не задано значение по умолчанию.

Копировать в буфер обмена
Процедура МояПроцедура(Параметр1, Параметр2 = "по умолчанию", Параметр3 = 16)КонецПроцедуры
// Параметр Параметр1 пропущен, значение параметра = Неопределено
// Параметр Параметр2 указан, значение параметра = 1
МояПроцедура( ,1);
// Параметр Параметр1 пропущен, значение параметра = Неопределено
// Параметр Параметр2 пропущен, значение параметра = "по умолчанию"
// Параметр Параметр3 опущен, значение параметра = 16
МояПроцедура(, ,);
// Ошибка несоответствия количества параметров
МояПроцедура();

Если при вызове метода параметры не передаются (пустой список параметров), то, тем не менее, круглые скобки обязательно требуется ставить.

При передаче с клиента на сервер и обратно строковых значений следует помнить, что эти значения не должны содержать символы, недопустимые с точки зрения спецификации XML версии 1.0 (http://www.w3.org/TR/xml/).

Совет. На стороне сервера такую проверку можно выполнить с помощью функции НайтиНедопустимыеСимволыXML().

Для конструкторов различных объектов понятие необязательности параметра трактуется особым образом. Если в описании конструктора указано, что параметр является необязательным, то это означает, что параметр может быть опущен, но не гарантируется, что этот параметр может быть пропущен. Опущенный параметр всегда имеет значение по умолчанию, а пропущенный параметр всегда получит значение Неопределено. В этом случае поведение конструктора зависит от реализации. Некоторые конструкторы могут воспринимать значение Неопределено как указание использовать некоторое значение по умолчанию, некоторые ‑ воспринимают это значение буквально (с возможным формированием ошибки времени исполнения). Можно сформулировать следующую рекомендацию по использованию необязательных параметров:

● Не рекомендуется пропускать необязательные параметры.

● Если конструктор обладает необязательными параметрами ‑ рекомендуется опускать все необязательные параметры, если не требуется явное указание какого-либо из них. В противном случае рекомендуется явно указывать все необязательные параметры, предшествующие параметру, который вы хотите указать явно.

4.7.5. Работа с коллекциями значений

Ряд объектов в языке системы «1С:Предприятие» представляет собой коллекции значений. Большинство коллекций имеют набор схожих методов и свойств, таких как Количество(), Индекс(), Добавить(), Удалить() и т. д. В качестве свойств коллекции, как правило, выступают ее элементы. Для коллекций доступен обход элементов коллекции посредством конструкции Для каждогоИзЦикл. Для большинства коллекций доступно обращение к элементам коллекции с помощью оператора [<Аргумент>] (квадратные скобки). Как правило, в качестве аргумента передается индекс элемента коллекции. Индексирование элементов коллекции начинается с 0. Это означает, что индекс последнего элемента равен количеству элементов в коллекции минус 1.

Если в процессе обхода коллекции происходит удаление или другие изменения состава элементов, то дальнейшее поведение системы не определено.

Подробнее описание конкретных коллекций, их свойств, методов и приемов работы с ними см. в описаниях конкретных объектов.

4.7.6. Использование номеров и индексов

В языке системы «1С:Предприятие» есть ряд объектов, отдельные части которых имеют нумерацию. К таким объектам, например, относится строка, символы которой имеют номер в строке, или табличный документ, строки и колонки которого имеют номер, и т. п. При обращении к частям объектов обычно используется понятие номер. Номера начинаются с 1.

При обращении к элементам коллекций используется понятие индекс. Индексирование элементов коллекций начинается с 0.

4.7.7. Работа с системными перечислениями

Во встроенном языке системы «1С:Предприятие» существует понятие системных перечислений. Они предназначены для определения некоторого ограниченного набора предопределенных значений. Доступ к системным перечислениям осуществляется как к свойствам глобального контекста его имени. Конкретные значения указываются через точку от имени системного перечисления. Системные перечисления используются, как правило, для задания значений параметров системных методов или свойств объектов, а также в качестве возвращаемых значений методов.

4.7.8. Работа с предопределенными значениями

4.7.8.1. С помощью менеджера объекта

Получить предопределенное значение на стороне сервера «1С:Предприятия» можно с помощью менеджера соответствующего объекта. Строка, определяющая получаемый реквизит, имеет следующий вид:

Копировать в буфер обмена
ТипПредопределенногоЗначения.ИмяОбъектаМетаданных.Значение

Рассмотрим составляющие этой строки подробнее:

ТипПредопределенногоЗначения ‑ для получения предопределенных значений доступно указание следующих типов данных (написание во множественном числе):

Справочники,

ПланыВидовХарактеристик,

ПланыСчетов,

ПланыВидовРасчета,

Перечисления.

ИмяОбъектаМетаданных ‑ указывается имя объекта метаданных так, как оно задано в конфигураторе.

Значение ‑ может быть одним из следующих:

● для перечислений указывается имя значения перечисления;

● для получения предопределенного значения указывается его имя, как оно задано в конфигураторе;

ТочкиМаршрута.ИмяТочки ‑ точка маршрута бизнес-процесса.

В случае, если требуется получить точку маршрута бизнес-процесса, строка, описывающая получаемое значение, будет выглядеть следующим образом:

Копировать в буфер обмена
БизнесПроцессы.ИмяОбъектаМетаданных.ТочкиМаршрута.ИмяТочкиМаршрута

Пример:

Копировать в буфер обмена
// Получение значения перечисления.
Вид = Перечисления.ВидыТоваров.Товар;
// Получение предопределенных данных справочника.
Элемент = Справочники.Валюта.Рубль;
// Точка маршрута бизнес процесса
Точка = БизнесПроцесс.Согласование.ТочкиМаршрута.Одобрение;

4.7.8.2. С помощью функции ПредопределенноеЗначение()

В связи с тем, что на стороне клиента недоступны прикладные объекты, получение предопределенных реквизитов с помощью менеджеров объектов становится невозможным. Поэтому для их получения существует метод глобального контекста ПредопределенноеЗначение(). Параметром этого метода является строка, описывающая то, какое предопределенное значение требуется получить. Синтаксис описания предопределенного значения совпадает с синтаксисом оператора Значение языка запросов (см. здесь).

Строка, определяющая получаемый реквизит, имеет следующий вид:

Копировать в буфер обмена
ТипПредопределенногоЗначения.ИмяОбъектаМетаданных.Значение

Рассмотрим составляющие этой строки подробнее:

ТипПредопределенногоЗначения ‑ для получения предопределенных значений доступно указание следующих типов данных (написание в единственном числе):

Справочник,

ПланВидовХарактеристик,

ПланСчетов,

ПланВидовРасчета,

Перечисление,

БизнесПроцесс.

ИмяОбъектаМетаданных ‑ указывается имя объекта метаданных так, как оно задано в конфигураторе.

Значение ‑ может быть одним из следующих:

● для перечислений указывается имя значения перечисления;

● для получения предопределенного значения указывается его имя, как оно задано в конфигураторе;

ТочкаМаршрута.ИмяТочки ‑ точка маршрута бизнес-процесса;

ПустаяСсылка ‑ для получения пустой ссылки.

В случае необходимости получить значение системного перечисления параметр метода будет выглядеть следующим образом: ИмяСистемногоПеречисления.ЗначениеСистемногоПеречисления.

Например:

Копировать в буфер обмена
ТипДиаграммы = ПредопределенноеЗначение("ТипДиаграммы.ВогнутаяПоверхность");

В случае если требуется получить точку маршрута бизнес-процесса, строка, описывающая получаемое значение, будет выглядеть следующим образом:

Пример:

Копировать в буфер обмена
// Получение значения перечисления.
Вид = ПредопределенноеЗначение("Перечисление.ВидыТоваров.Товар");
// Получение значения пустой ссылки.
ПустаяСсылка =
    ПредопределенноеЗначение("Документ.РасходнаяНакл.ПустаяСсылка");
// Получение предопределенных данных справочника.
Элемент = ПредопределенноеЗначение("Справочник.Валюта.Рубль");
// Точка маршрута бизнес процесса
Точка =    ПредопределенноеЗначение("БизнесПроцесс.Согласование.ТочкаМаршрута.Одобрение");

4.7.9. Синхронные и асинхронные методы работы

4.7.9.1. Общая информация

Сеанс работы с информационной базой определяет активного пользователя базы и поток управления этого пользователя. В рамках сеанса, программа на встроенном языке «1С:Предприятие» выполняется последовательно в одном потоке, таким образом ‑ никакие два фрагмента кода на встроенном языке не могут выполняться одновременно. Встроенный язык в своем изначальном виде работает синхронно (в том числе и методы объектной модели). Синхронный вызов блокирует основной поток до тех пор, пока не завершится вызванный метод (со всеми вложенными). Это особенно неприятно в тех случаях, когда, например, выполняется ожидание какой-то реакции пользователя (ответ на вопрос). Веб-браузеры не поддерживают синхронное исполнение некоторых операций, которые во встроенном языке являются синхронными. Веб-браузер требует, чтобы эти операции были асинхронными. Асинхронные методы ‑ это такие методы, завершение (и исполнение) которых не синхронно с кодом, из которого они вызваны. Асинхронные вызовы предназначены для решения одной задачи: в некоторых случаях предотвратить блокирование основного потока.

Для реализации асинхронной схемы использования в клиентском приложении, кроме основного потока существует очередь асинхронных задач. Задачи из этой очереди выполняются основным потоком в тот момент, когда основной поток сможет это сделать. Где конкретно выполняется асинхронный метод ‑ является деталью реализации. Это не влияет на понимание и использование механизма. Однако важно заметить, что рассматриваемый механизм не имеет отношения к многопоточности.

Асинхронные (по сути) методы могут содержаться только в объектной модели встроенного языка системы «1С:Предприятие». Но наличие асинхронных методов в объектной модели требует, чтобы разработчик понимал, как работает эта конструкция.

Рассмотрим разницу между синхронной и асинхронной работой. Как уже было сказано выше, при синхронном подходе вызов какого-либо метода приведет к тому, что работа вызывающего кода будет остановлена до тех пор, пока не завершится вызов метода (со всеми вложенными вызовами). Любой вызов процедуры или функции встроенного языка всегда является синхронным вызовом. Но завершение метода зависит от используемой схемы работы: в синхронной схеме возврат из метода произойдет только при его фактическом завершении, а при асинхронной схеме ‑ возможны несколько возвратов до фактического завершения работы.

Если рассмотреть пример с кодом, который показывает предупреждение, ожидает нажатия кнопки и выводит какой-то текст, то синхронный вариант будет выглядеть следующим образом:

Копировать в буфер обмена
Текст = "Текст предупреждения";
Предупреждение(Текст);
Сообщить("Закрыли предупреждение");

При исполнении этого кода мы увидим, что текст Закрыли предупреждение будет выведен после того, как в диалоге нажали кнопку Ок. Если вместо метода Предупреждение() будет вызов кого-то метода на встроенном языке, то исполнение функции Сообщить() произойдет только после того, как выполниться наш метод (со всеми вложенными вызовами, если таковые есть).

При асинхронном подходе вызов метода выполняется как обычно, но управление возвращается вызывающему коду до того, как асинхронный метод завершит свою работу. После этого вызывающий код продолжает свое выполнение. При этом вызванный (асинхронный) метод гарантирует, что после завершения своей работы он оповестит о своем завершении заинтересованное «лицо» (если такое оповещение требуется). Способ оповещения зависит от того, какую схему использования асинхронных методов использует разработчик. Все вышеописанное верно только для тех методов, для которых заявлена поддержка асинхронной работы.

Рассмотрим вышеприведенный пример в асинхронной схеме. Асинхронный вариант программы будет отличаться от синхронного варианта совсем немного. Но работать он будет абсолютно по-другому:

Копировать в буфер обмена
Текст = "Текст предупреждения";
ПоказатьПредупреждение( , Текст);
Сообщить("Закрыли предупреждение");

В этом примере текст Закрыли предупреждение будет показан до того, как в диалоге будет выполнено хоть какое-то действие. Таким образом, мы явным образом наблюдаем ранее описанную особенность асинхронного выполнения: исполнение на стороне вызывающего кода продолжится до того, как полностью закончилось исполнение вызванного метода. Под «исполнением кода» понимается полное выполнение метода (включая все вложенные) и выполнение всех положенных действий (включая интерактивные).

Для реализации «асинхронного программирования» платформа «1С:Предприятие» предлагает две схемы:

● Схему с реализацией методов обратного вызова (подробнее см. здесь).

● Схему с реализацией «обещаний» асинхронных методов (подробнее см. здесь).

Более подробно каждая из описанных схем будет описана далее.

В системе «1С:Предприятие» асинхронную технику можно использовать для работы:

1. С блокирующими окнами (см. здесь);

2. Расширением работы с файлами (см. здесь);

3. Расширением криптографии (см. здесь);

4. Внешними компонентами (см. здесь).

Все варианты предполагают асинхронное использование только на стороне клиентского приложения. На стороне сервера по-прежнему доступны синхронные техники работы, за исключением работы с блокирующими окнами (по причине отсутствия пользовательского интерфейса на стороне сервера).

4.7.9.2. Асинхронность через обратный вызов

При асинхронном подходе вызов метода выполняется как обычно, но управление возвращается вызывающему коду до фактического завершения асинхронного метода, и исполнение вызывающего кода продолжается. При этом вызванный метод гарантирует, что после завершения своей работы он оповестит о своем завершении заинтересованное «лицо» (если такое оповещение требуется). Оповещение выполняется с помощью вызова специального метода обратного вызова, который передается в вызываемый метод объекта.

С точки зрения имен методов встроенного языка, асинхронные методы отличаются от синхронных тем, что имя асинхронного метода (как правило) начинается со слов Начать или Показать. Знание этой особенности позволит упростить поиск аналогов синхронных методов.

Рассмотрим организацию асинхронного вызова на примере отображения предупреждения. Для асинхронного вывода предупреждения используется метод ПоказатьПредупреждение(). Для того, чтобы сообщить о том, что диалог предупреждения закрыт, в этот метод передается описание оповещения. Описание оповещения содержит имя и месторасположения процедуры или функции, которая будет вызвана системой после закрытия диалога. Соответственно, метод ПоказатьПредупреждение() отличается от метода Предупреждение() тем, что в методе ПоказатьПредупреждение() существует еще один параметр, через который и передается описание оповещения. Эта разница означает, что метод поддерживает асинхронную работу.

Пример:

Копировать в буфер обмена
&НаКлиенте
Процедура ВыполнитьКоманду(Команда)
    ОбратныйВызов = Новый ОписаниеОповещения("ПредупреждениеЗавершение", ЭтотОбъект);
    ПоказатьПредупреждение(ОбратныйВызов, "Закрытие формы обрабатывается отдельно");
КонецПроцедуры
&НаКлиенте
Процедура ПредупреждениеЗавершение(ДополнительныеПараметры) Экспорт
    // какие то действия
КонецПроцедуры

Для описания оповещения используется специальный объект ОписаниеОповещения. При его создании необходимо указать имя метода обработки оповещения, место расположения метода и дополнительные параметры, если необходимо. Дополнительные параметры могут использоваться методом обработки оповещения для своей работы. В приведенном выше примере дополнительные параметры не указываются.

Также следует отметить, что методы обработки оповещений (обратного вызова) могут располагаться только на стороне клиентского приложения в модуле формы, общем модуле и модуле команды. Процедура обратного вызова должна быть описана с ключевым словом Экспорт.

Если необходимо вызвать обработчик оповещения в каком-либо месте кода на встроенном языке, то можно использовать метод ВыполнитьОбработкуОповещения() (при этом описание вызываемого оповещения может быть создано и передано из других участков кода, например в качестве параметра метода). В качестве обработчика оповещения может выступать как процедура, так и функция. В случае, если обработчиком оповещения выступает функция, метод ВыполнитьОбработкуОповещения() вернет результат работы функции. Если обработчик оповещения ‑ это процедура, то метод ВыполнитьОбработкуОповещения() вернет значение Неопределено.

Из примера, приведенного выше, видно, что работа с асинхронными методами существенно изменяет подходы к разработке. Основное изменение заключается в том, что единый фрагмент текста на встроенном языке (для случаев использования синхронных методов) разбивается на несколько изолированных фрагментов (в случае использования асинхронных методов).

Так, если в приведенном примере после отображения предупреждения должны были выполняться какие-то действия (именно после реакции пользователя, а не после вызова метода!), то эти действия следует перенести в процедуру ПредупреждениеЗавершение().

Более сложные алгоритмы, очевидно, приведут и к более сложному рефакторингу исходного текста программы. Возможно, что переработки потребует сам алгоритм, а не только его реализация, которая может существенно усложниться. Например, в синхронном режиме, если алгоритму требуется какая-либо реакция пользователя, то эту реакцию получают непосредственно в том месте, где эта реакция требуется. Если перерабатывать такой алгоритм с использованием асинхронной техники, то логично разработать отдельный диалог, в котором пользователь ответит на все возможные вопросы, а затем результат этого «опроса» будет передан методу, который реализует нужный алгоритм. При этом вопросы «по месту» больше задавать не требуется, а вместо этого следует анализировать результаты «опроса» пользователя.

Кроме изменения подходов к разработке, при использовании асинхронных методов несколько изменяется и подход к обработке ошибок. Например, ошибки могут возникать в то время, когда код на встроенном языке не исполняется и нельзя использовать конструкцию Попытка … Исключение. Для обработки таких ситуаций при создании обработчика оповещения можно указать процедуру, которая будет вызываться системой при возникновении ошибки. Примером такой ошибки может быть ошибка, возникающая в процессе удаления файлов.

Пример:

Копировать в буфер обмена
&НаКлиенте
Процедура УдалитьВсеФайлыКаталога(ПутьККаталогу)
    ОбратныйВызов = Новый ОписаниеОповещения("УдалитьЗавершение", ЭтотОбъект, , "УдалитьОшибка", ЭтотОбъект);
    НачатьУдалениеФайлов(ОбратныйВызов, ПутьККаталогу, ПолучитьМаскуВсеФайлыКлиента());
КонецПроцедуры
&НаКлиенте
Процедура УдалитьЗавершение(ДополнительныеПараметры) Экспорт
    Сообщить("Удаление успешно завершено");
КонецПроцедуры
&НаКлиенте
Процедура УдалитьОшибка(ИнформацияОбОшибке, СтандартнаяОбработка, ДополнительныеПараметры) Экспорт
    Сообщить("При удалении обнаружена ошибка: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
КонецПроцедуры

В приведенной реализации есть одна особенность: если во время удаления файлов произойдет ошибка, то наряду с сообщением об ошибке в окне сообщений платформы, пользователь увидит также и системный диалог с сообщением об ошибке. В том случае, если системный диалог не нужен ‑ следует в обработчике УдалитьОшибка() установить параметр СтандартнаяОбработка в значение Ложь.

Также следует учитывать, что указание обработчика ошибок в описании оповещения игнорируется при использовании асинхронных методов работы с блокирующими окнами (см. здесь).

Еще одной особенностью работы с асинхронными вызовами является их отладка. В данный момент отладчик умеет отлаживать действия, которые синхронно выполняются в предмете отладки (фактически, по инициативе отладчика).

В случае использования асинхронных вызовов асинхронный вызов выполняется в момент времени, отличный от фактического выполнения строки кода на встроенном языке, которая инициирует данный вызов. В связи с этим, если во время фактического исполнения асинхронного вызова в этом вызове случается ошибка, отладчик не может корректно определить состояние отлаживаемого приложения. Поэтому недоступна текущая строка исполнения, стек вызовов и так далее.

4.7.9.3. Асинхронность через обещания

4.7.9.3.1. Общая информация

Основу данной схемы работы составляет объект встроенного языка Обещание. Обещание представляет собой результат асинхронной функции, выполнение которой еще не завершено, но ее завершение ожидается в будущем (обещается). Объект Обещание возвращается асинхронной функцией в качестве результата своей работы.

Пример с отображением предупреждения и выводом сообщения пользователю после(!) закрытия окна предупреждения будет выглядеть следующим образом:

Копировать в буфер обмена
Текст = "Текст предупреждения";
Ждать ПредупреждениеАсинх(Текст);
Сообщить("Закрыли предупреждение");

В результате своей работы асинхронная функция может или вернуть какое-то значение (результат работы функции) или сгенерировать исключение, если в процессе работы функции произошла ошибка. Для того, чтобы получить результат работы асинхронной функции, предназначен оператор Ждать. У этого оператора есть единственный параметр ‑ это объект типа Обещание. В результате система дожидается завершения работы асинхронной функции, которая вернула ожидаемое обещание и либо получает результат работы функции либо генерирует исключение. Но ожидание завершения происходит не в том месте кода, где использован оператор Ждать. При выполнении оператора Ждать произойдет возврат управления в вызывающий код. Подробнее про эту особенность поговорим чуть позже.

Важным моментом является тот факт, что объект типа Обещание является обычным объектом платформы. Его можно присваивать переменной, передавать в другие методы и использовать в выражениях. Другими словами: вызвать асинхронную функцию мы можем в одном месте, а дождаться завершения работы этой функции ‑ совершенно в другом. Существенным моментом является то, что обещание не может быть передано на сервер. Получить обещание на сервере также не возможно.

Несколько переделаем предыдущий пример. Вместо отображения предупреждения, сделаем отображение вопроса: Продолжить выполнение?. В диалоге будут две кнопки Да и Нет.

Копировать в буфер обмена
Текст = "Продолжить работу?";
Результат = Ждать ВопросАсинх(Текст, РежимДиалогаВопрос.ДаНет);
Если Результат = КодВозвратаДиалога.Да Тогда
    // продолжаем работу
    Сообщить("Продолжаем работу");
Иначе
    // завершаем работу
    Сообщить("Завершаем работу");
    Возврат;
КонецЕсли;

Этот пример демонстрирует, что обещание нужно использовать «в комплекте» с оператором Ждать. Если получить обещание, но не использовать Ждать, то не будет переменной Результат. Следовательно ‑ нельзя будет проверить, что ответил пользователь. После того, как асинхронная функция завершила свою работу, оператор Ждать получает из обещания фактическое возвращаемое значение (выполняет обещание).

Если асинхронная функция, во время своей работы, может сформировать исключение, то его также можно перехватить. Для этого, как и в синхронном коде, следует использовать конструкцию Попытка … Исключение. Но исключение будет перехвачено только в том случае, если обещание используется совместно с оператором Ждать. Например, вот так можно написать код поиска файлов по маске:

Копировать в буфер обмена
ОбещаниеФайлов = НайтиФайлыАсинх(Ждать КаталогВременныхФайловАсинх(), "*.xml");
Попытка
    Файлы = Ждать ОбещаниеФайлов;
Исключение
    // при поиске файлов случилась ошибка
КонецПопытки;

Если во время поиска файлов произойдет какое-либо исключение ‑ это исключение будет перехвачено оператором Попытка.

В результате использования асинхронности через обещания, программист получает исходный код, который очень близок к своему синхронному аналогу. Асинхронность через обещания делает более простой адаптацию синхронного кода для использования в асинхронной схеме. Такой способ упрощает программирование некоторых алгоритмов на стороне клиентского приложения и делает их сопровождение более простой задачей.

4.7.9.3.2. Схема именования методов

Асинхронные методы платформы, которые используют обратные вызовы, выделяются префиксом Начать или Показать (см. здесь). Аналогично, платформенные функции, которые возвращают объект типа Обещание, выделяются с помощью суффикса Асинх. Но ключевым признаком того, что функция может использоваться для асинхронной работы с использованием обещаний ‑ это тот факт, что функция возвращает объект типа Обещание. В результате некоторое множество функций платформы существуют в трех вариантах:

● Синхронный вариант ‑ метод описывает совершаемое действие. Например, Вопрос() или НайтиФайлы(). Основной поток блокируется до момента завершения вызова метода.

● Асинхронный вариант через обратный вызов ‑ название метода начинается с префикса Начать или Показать. Например, ПоказатьВопрос() или НачатьПоискФайлов(). О завершении метода выполняется оповещение с помощью метода обратного вызова, переданного в качестве параметра.

● Асинхронный вариант через обещания ‑ название метода оканчивается на суффикс Асинх. Например, ВопросАсинх(), НайтиФайлыАсинх(). В этом случае используется объект Обещание и возможность дождаться завершения с помощью оператора Ждать.

Еще одной особенностью асинхронности через обещание является то, что использование оператора Ждать допустимо только в тех процедурах или функциях, которые объявлены с модификатором Асинх:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура ЖдатьПредупреждение(Команда)
    Текст = "Текст предупреждения";
    Ждать ПредупреждениеАсинх(Текст);
    Сообщить("Закрыли предупреждение");
КонецПроцедуры

Если у процедуры ЖдатьПредупреждение() убрать модификатор Асинх, при попытке сохранения модуля конфигуратор выдаст ошибку:

Копировать в буфер обмена
Оператор Ждать (Await) может употребляться только в асинхронных процедурах или функциях
    <<?>>Ждать ПредупреждениеАсинх(Текст);
4.7.9.3.3. Особенности асинхронных методов

Асинхронной может быть как функция, так и процедура. Как было сказано выше, для того, чтобы метод стал асинхронным, его необходимо описать с использованием модификатора Асинх. Метод, описанный с таким модификатором, получает возможность использования оператора Ждать. При разработке асинхронных методов следует помнить, что параметры в асинхронные методы всегда передаются по значению. Таким образом, ключевое слово Знач в описании асинхронного метода игнорируется. Не поддерживается возможность передавать параметр асинхронного метода по ссылке ‑ только по значению. В результате вышесказанного, следующие два описания методов полностью эквивалентны:

Копировать в буфер обмена
Асинх Функция КопироватьФайлыАсинх(ИсхКаталог, ЦелКаталог)
Асинх Функция КопироватьФайлыАсинх(Знач ИсхКаталог, Знач ЦелКаталог)

Асинхронные функции всегда возвращают объект типа Обещание. Асинхронные процедуры ничего не возвращают. Разберем эти особенности. Как уже было сказано выше, асинхронная функция всегда возвращает объект типа Обещание. Но ведь функция должна вернуть именно то значение, которое хочет вернуть автор функции. Для преобразования обещания в конкретное значение ‑ служит оператор Ждать. Т. е. в том случае, когда нам необходимо получить фактическое значение результата работы функции, необходимо написать код, уже встречавшийся ранее в этом разделе (в следующей строке примера приведен синхронный аналог вызова):

Копировать в буфер обмена
Результат = Ждать АсинхроннаяФункция(Параметр1, Параметр2);
Результат = СинхроннаяФункция(Параметр1, Параметр2);

При обработке исключений следует понимать следующее: исключение, которое произошло при выполнении асинхронного метода невозможно перехватить привычным, синхронным способом. Другими словами, следующий пример не приведет к перехвату исключения:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура ОбработкаИсключения(Команда)
    Попытка
   ЕстьИсключение();
    Исключение
   Сообщить("Поймано исключение: " + ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецПроцедуры
&НаКлиенте
Асинх Функция ЕстьИсключение()
    ВызватьИсключение "Исключение в асинхронной функции";
КонецФункции

Обработать исключение можно одним из следующих способов:

● Обработать исключение в самом асинхронном методе, например, с помощью конструкции Попытка … Исключение вокруг кода, который может сформировать исключение. Другими словами можно не допустить ситуации, когда асинхронная функция закончится исключением.

● Поместив оператор Ждать с обещанием аснхронной функции в конструкцию Попытка … Исключение в коде, из которого вызвана асинхронная функция. Далее приведен пример такой обработки исключения:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура ОбработкаИсключения(Команда)
    Попытка
   Ждать ЕстьИсключение();
    Исключение
   Сообщить("Поймано исключение: " + ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецПроцедуры
&НаКлиенте
Асинх Функция ЕстьИсключение()
    ВызватьИсключение "Исключение в асинхронной функции";
КонецФункции

Также необходимо понимать, что перехватывать исключение необходимо не в месте вызова асинхронной функции, а в месте использования оператора Ждать с обещанием, которое вернула асинхронная функция. Можно модифицировать предыдущий пример так, что отдельно будет получаться обещание и отдельно будет выполняться его ожидание:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура ОбработкаИсключения(Команда)
    Обещание = ЕстьИсключение();
    Попытка
   Ждать Обещание;
    Исключение
   Сообщить("Поймано исключение: " + ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецПроцедуры
&НаКлиенте
Асинх Функция ЕстьИсключение()
    ВызватьИсключение "Исключение в асинхронной функции";
КонецФункции

В данном примере исключение будет перехвачено, т. к. в попытку «обернуто» ожидание обещания. Но в качестве исходной строки с ошибкой будет указана не строка, где размещен оператор Ждать, а строка с фактическим вызовом асинхронной функции.

Еще одной особенностью работы с обещаниями является то, что процедура не возвращает никакого значения. Из этого следует, что процедура не может вернуть объект типа Обещание. Следовательно, перехватить исключение, которое возникает в асинхронной процедуре, за ее (процедуры) пределами ‑ невозможно. Это исключение попадет в обработчик события ОбработкаОтображенияОшибки, а если этого обработчика нет ‑ будет сразу показана пользователю. Таким образом, асинхронная процедура интересна, в первую очередь, как обработчик событий, которые формирует платформа (например, в форме). Если для процедуры не указан модификатор Асинх ‑ в ней нельзя использовать оператор Ждать.

Следующая особенность использования асинхронных методов основывается на том, что все параметры методов передаются по значению. Отсюда вытекает то, что обработчики событий, которые что-то возвращают через свои параметры (например, параметр СтандартнаяОбработка), не смогут полноценно работать в асинхронном варианте. Решить эту проблему можно следующим образом: разделить код обработчика на синхронный и асинхронный участки. Сам обработчик будет синхронным и в нем будет выполняться вся логика, которая применима для формирования значений возвращаемых параметров. Асинхронный участок будет находиться в асинхронной функции, которая будет вызвана из синхронного обработчика. Но эта функция не сможет вернуть в синхронный код никаких значений, т.к. оператор Ждать может быть использован только в асинхронной функции.

Сформулируем общие особенности использования асинхронных методов:

● При вызове асинхронного метода параметры всегда передаются по значению.

● Все обещания (объект типа Обещание), которые возвращают асинхронные функции, рекомендуется использовать в операторах Ждать. В противном случае будут потеряны возвращаемые значения функций и исключения, возникающие в функциях.

● Процедуру имеет смысл делать асинхронной в том случае, когда процедура является обработчиком события и в этой процедуре необходимо ожидать завершения исполнения асинхронных функций (оператор Ждать). Во всех остальных случаях рекомендуется делать асинхронные функции.

● Обработчик необходимо сохранять синхронным в том случае, когда он должен возвращать значения через свои параметры. В этом случае вся асинхронная часть метода должна быть вынесена в асинхронную процедуру.

4.7.9.3.4. Как это работает

Перед рассмотрением примера использования асинхронных методов, имеет смысл упомянуть одну особенность работы этих методов, на которой ранее не делалось явного акцента. Когда в методе используется оператор Ждать, можно сказать, что такой метод имеет не только несколько промежуточных возвратов, которые возникают в тот момент, когда оператор Ждать ожидает выполнения обещания. Такой метод имеет и несколько «промежуточных» точек входа в метод. «Промежуточная» точка входа ‑ это фактически, тот же оператор Ждать, но который «дождался» выполнения обещания. Происходит выполнение обещания, результат работы асинхронной функции становится доступен для использования или происходит генерация исключения, которое произошло в асинхронной функции, но было «спрятано» в обещании. Другими словами, именно отсюда будет продолжено выполнение асинхронного метода после того, как выполнится обещание. Демонстрирует такое поведение простой пример:

Копировать в буфер обмена
Асинх Процедура КопированиеФайлов(Команда)
    Текст = "Выполнить копирование файлов?";
    Обещание = ВопросАсинх(Текст, РежимДиалогаВопрос.ДаНет);
    Результат = Ждать Обещание;
    Если Результат = КодВозвратаДиалога.Да Тогда
   // продолжаем работу
   КопироватьФайлАсинх(ФайлИсточник, ФайлПриемник);
   Попытка
    Ждать ОбещаниеКопирования;
    Сообщить("Файл скопирован");
   Исключение
    // при копировании произошла ошибка
   КонецПопытки;
    КонецЕсли;
КонецПроцедуры

В процедуре КопированиеФайлов() будет две точки промежуточного возврата и две промежуточных точки входа:

Результат = Ждать Обещание ‑ это точка промежуточного возврата и она же ‑ промежуточная точка входа.

Ждать ОбещаниеКопирования ‑ это промежуточная точка возврата и эта же строка будет промежуточной точкой входа.

Теперь можно рассмотреть простой пример, поясняющий схему работы «асинхронного программирования». В этом примере будут перебираться все файлы, которые размещены в каталоге временных файлов, над каждым файлом выполняется какое-то действие и в качестве результата будет возвращено количество обработанных файлов. Пример сделан для пояснения смысла, а не для создания оптимального алгоритма. В примере, для упрощения описания работы, выполнена нумерация строк:

Копировать в буфер обмена
01|&НаКлиенте
02|Асинх Процедура ВыполнитьКоманду(Команда)
03|    ЧислоФайлов = Ждать ПоказатьФайлыАсинх();
04|    Сообщить("Число файлов = " + ЧислоФайлов);
05|КонецПроцедуры
06|
07|&НаКлиенте
08|Асинх Функция ПоказатьФайлыАсинх()
09|    Каталог = Ждать КаталогВременныхФайловАсинх();
10|    СписокФайлов = Ждать НайтиФайлыАсинх(Каталог, ПолучитьМаскуВсеФайлы());
11|    Счетчик = 0;
12|    Для каждого Файл Из СписокФайлов Цикл
13|  // что-то делаем
14|  Счетчик = Счетчик + 1;
15|    КонецЦикла;
16|    Возврат Счетчик;
17|КонецФункции

Процедура ВыполнитьКоманду() является обработчиком события ПриНажатии кнопки формы. Исполнение код начинается с нажатия пользователем на эту кнопку:

● Выполнение начинается со строки 02. Затем, в строке 03, вызывается функция ПоказатьФайлыАсинх().

● В строке 09 происходит вызов асинхронной функции платформы КаталогВременныхФайловАсинх(). Т. к. это асинхронная функция, то она возвращает обещание своего результата, которое является аргументом оператора Ждать. Исполнение оператора Ждать приводит к тому, что выполнение функции ПоказатьФайлыАсинх() прерывается и управление возвращается в процедуру ВыполнитьКоманду(), на строку 03.

● В силу того, что ПоказатьФайлыАсинх() возвращает Обещание, а вызов функции ПоказатьФайлыАсинх() является параметром оператора Ждать, выполнение процедуры ВыполнитьКоманду() в этот момент завершается.

● В результате выполнения встроенного языка в системе существуют два ожидания:

1. Когда завершится выполнение функции ПоказатьФайлыАсинх() (строка 03).

2. Когда завершится выполнение функции КаталогВременныхФайловАсинх() (строка 09).

● Ровно в тот момент, как завершилось выполнение функции КаталогВременныхФайловАсинх(), управление возвращается в строку 09 (включая восстановление локальных переменных), оператор Ждать в этой строке «дожидается» обещанного завершения работы функции. Ожидание прекратилось, в переменную Каталог помещен каталог временных файлов пользователя. Управление передано на строку 10.

● В строке 10 вызывается асинхронный метод платформы НайтиФайлыАсинх(). Логика работы с ним аналогична логике работы с методом КаталогВременныхФайловАсинх(). Управление передается системе «1С:Предприятие». После «выполнения» строки 10 в системе по-прежнему остается два ожидания:

1. Когда завершится выполнение функции ПоказатьФайлыАсинх() (строка 03).

2. Когда завершится выполнение функции НайтиФайлыАсинх() (строка 10).

● В предыдущем пункте слово «выполнение» взято в кавычки потому, что собственно выполнение еще не завершилось. Платформа определила необходимость ожидать завершения работы асинхронного кода (оператор Ждать) и приостановила работу функции ПоказатьФайлыАсинх(). В связи с тем, что фактического завершения работы функции ПоказатьФайлыАсинх() не произошло ‑ ожидание в строке 03 продолжается. Т. к. более никакого кода на встроенном языке выполнять не требуется ‑ управление возвращается платформе.

● После того, как поиск файлов завершился, управление передается на строку 10, выполняется восстановление контекста (значения локальных переменных), оператор Ждать в строке 10 завершает ожидание исполнения. В переменную СписокФайлов помещается массив с файлами из каталога временных файлов.

● Теперь в системе имеется только одно ожидание: на строке 03 система ждет фактического завершения работы функции ПоказатьФайлыАсинх().

● Управление передается на строку 11 и далее по тексту функции ПоказатьФайлыАсинх().

● В строке 16 происходит фактическое завершение работы функции ПоказатьФайлыАсинх() и происходит возврат количества обработанных файлов.

● После выполнения фактического возврата, происходит завершение ожидания в строке 03 и выполнение передается на строку 04.

● На экран выводится сообщение о количестве обработанных файлов, и работа обработчика логически завершается в строке 05.

В этой схеме важно понимать следующее: когда происходит возобновление исполнения встроенного языка после завершения работы оператора Ждать (строки 03, 09 и 10), инициатором вызова (и, фактически, вершиной стека вызовов) будет интерпретатор встроенного языка платформы. Но для того, чтобы программисту было проще понять, где он находится, в отладчике будет выполняться реконструкция того стека вызовов, который должен был привести к выполнению той или иной строки встроенного языка. Другими словами, отладчик пытается показать стек таким, каким стек был-бы при выполнении аналогичной, но полностью синхронной программы.

4.7.9.3.5. Примеры использования

Удаление файлов (аналог примера с обратными вызовами)

Для того чтобы удалить все файлы во временном каталоге, необходимо использовать примерно следующий код:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура УдалитьФайлыВременногоКаталога(Команда)
    Попытка
   Ждать УдалитьФайлыАсинх(Ждать КаталогВременныхФайловАсинх(), ПолучитьМаскуВсеФайлы());
    Исключение
   Сообщить("При удалении файлов обнаружена ошибка: " + ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецПроцедуры

Копирование файлов

Ниже приведена реализация клиентского метода копирования всех файлов между каталогами, которые указаны на форме в реквизитах КаталогОткуда и КаталогКуда. Кнопка формы называется ВыполнитьКопирование и в модуле формы расположен следующий код:

Копировать в буфер обмена
&НаКлиенте
Асинх Процедура ВыполнитьКопирование(Команда)
    Попытка
   СколькоФайлов = Ждать КопироватьФайлыАсинх(КаталогОткуда, КаталогКуда);
   Сообщить("Скопировано файлов: " + СколькоФайлов);
    Исключение
   ОписаниеОшибки = ОбработкаОшибок.ПредставлениеОшибкиДляПользователя(ИнформацияОбОшибке());
   ПредупреждениеАсинх("При копировании файлов произошла ошибка: " + Символы.ПС + ОписаниеОшибки);
    КонецПопытки
КонецПроцедуры
&НаКлиенте
Асинх Функция КопироватьФайлыАсинх(ИсхКаталог, ЦелКаталог)
    СписокФайлов = Ждать НайтиФайлыАсинх(ИсхКаталог, ПолучитьМаскуВсеФайлы(), Ложь);
    Счетчик = 0;
    Для Каждого Файл Из СписокФайлов Цикл
   ИсхФайл = ИсхКаталог + ПолучитьРазделительПути() + Файл.Имя;
   ЦелФайл = ЦелКаталог + ПолучитьРазделительПути() + Файл.Имя;
   Ждать КопироватьФайлАсинх(ИсхФайл, ЦелФайл);
   Счетчик = Счетчик+1;
    КонецЦикла;
    Возврат Счетчик;
КонецФункции

4.7.9.4. Работа в веб-клиенте

Работа в веб-клиенте имеет некоторые особенности. Эти отличия вызваны особенностями реализации веб-браузеров (отсутствие поддержки модальных окон, синхронных вызовов, особенности модели безопасности). При работе в веб-клиенте не поддерживается синхронная техника работы (во всех вариантах). Для работы с файлами (см. здесь) и криптографией (см. здесь) требуется наличие специальных расширений, установленных в используемом веб-браузере. При использовании веб-браузера Google Chrome или Mozilla Firefox, перед установкой расширений платформы, необходимо выполнить установку расширения веб-браузера Расширение для работы с 1С:Предприятием, которое устанавливается из магазина расширений соответствующего веб-браузера. При необходимости, переход на страницу установки будет выполнен автоматически. Без установки этого расширения будет невозможно использование расширений платформы.

Для работы с расширениями необходимо:

● Соответствующим образом настроить веб-браузер (подробно написано в книге).

● Расширение работы с файлами:

● Установить расширение ‑ с помощью одного из методов УстановитьРасширениеРаботыСФайламиАсинх(), УстановитьРасширениеРаботыСФайлами() или НачатьУстановкуРасширенияРаботыСФайлами(). Это интерактивное действие, которое необходимо выполнить один раз для каждого пользователя локального компьютера, использующего расширение.

● Подключить расширение ‑ с помощью метода ПодключитьРасширениеРаботыСФайламиАсинх(), ПодключитьРасширениеРаботыСФайлами() или НачатьПодключениеРасширенияРаботыСФайлами().

● Расширение работы с криптографией:

● Установить расширение ‑ с помощью метода УстановитьРасширениеРаботыСКриптографиейАсинх(), УстановитьРасширениеРаботыСКриптографией() или НачатьУстановкуРасширенияРаботыСКриптографией(). Это интерактивное действие, которое необходимо выполнить один раз для каждого пользователя локального компьютера, использующего расширение.

● Подключить расширение ‑ с помощью метода ПодключитьРасширениеРаботыСКриптографиейАсинх(), ПодключитьРасширениеРаботыСКриптографией() или НачатьПодключениеРасширенияРаботыСКриптографией().

● Внешние компоненты ‑ более подробно о работе с внешними компонентами см. здесь.

4.7.10. Преобразование значений при изменении типа

Данный раздел описывает правила преобразования значений в тех случаях, когда значение одного типа присваивается в реквизит другого типа. Под «другим» типом понимается любая ситуация: другой тип (простой тип), другой состав типов (составной тип), другие квалификаторы типа и т. д. Преобразование значений может выполняться в случае реструктуризации информационной базы (при изменении типа реквизита), при присваивании значения реквизиту объекта информационной базы и в других аналогичных случаях.

Правила преобразования значений:

Ситуация

Правила преобразования значения

Булево в Дата

Реквизит принимает пустое значение типа Дата.

Булево в Строка

Значение конвертируется в его представление.

Булево в Число

Значение Ложь конвертируется в значение 0.

Значение Истина конвертируется в значение 1.

Строка в Булево

Если строка содержит локализованное представление значения типа Булево, то это значение конвертируется в значение типа Булево.

Если строка содержит одно из значений True, Истина, False или Ложь (регистр символов не играет роли), то это значение конвертируется в значение типа Булево.

В остальных случаях реквизит принимает значение Ложь.

Строка в Дата

Если в строке задано локализованное представление даты, то это значение конвертируется в значение типа Дата.

Если в сроке указано значение вида ГГГГММДДЧЧММСС, ГГГГММДДЧЧММ или ГГГГММДД, то это значение конвертируется в значение типа Дата.

В остальных случаях реквизит получает пустое значение типа Дата.

Строка -> Число

Если в строке задано локализованное представление числа, то это значение конвертируется в значение типа Число.

Если в сроке указано значение вида [-]d[…d][[.][d…d]], то это значение конвертируется в значение типа Число.

В остальных случаях реквизит принимает значение 0.

Число в Дата

Реквизит принимает пустое значение типа Дата.

Число в Булево

Значение 0 конвертируется в значение Ложь.

Значение 1 конвертируется в значение Истина.

Число в Строка

Значение конвертируется в представление.

Запрет отрицательных числе

Отрицательные значения заменяются на значение 0.

Сокращение состава перечисления

Если тип значение реквизита является составным, то в реквизит записывается значение Неопределено.

Если типом значения реквизита является «сокращаемое» перечисление, то в реквизит будет записана пустая ссылка на перечисление.

Уменьшение длины строки

Значение в реквизите усекается справа до нужной длины.

Уменьшение дробной части числа

Значение округляется в соответствии с установленным режимом округления.

Уменьшение целой части числа

Значение заменяется на число, состоящее из цифр «9». Количество цифр соответствует разрядности реквизита, получающего значение.

4.8. Особенности различных вариантов запуска системы

Система «1С:Предприятие» может использоваться в файловом и клиент-серверном вариантах, во внешнем соединении, а также в виде Интернет-сервисов.

Конфигуратор позволяет настроить использование процедур и функций общих модулей и модулей объектов для каждого варианта.

4.8.1. Исполнение процедур и функций

Для указания разрешения применения процедур и функций различных модулей (про виды модулей см. здесь) используют инструкции препроцессору и директивы компиляции.

4.8.1.1. Различие инструкций препроцессора и директив компиляции

Инструкции препроцессора и директивы компиляции предназначены для того, чтобы оставить в скомпилированном модуле только то, что действительно должно присутствовать в том или ином контексте. При этом инструкции препроцессора действуют на исходный текст модуля (т. е. удаляют из модуля текст, который не может в нем находиться), а директивы компиляции действуют на структурные единицы программного кода (методы ‑ процедуры или функции, а также объявления переменных).

Фактически все программные модули, присутствующие в системе, можно разделить на две большие группы модулей:

● Модули, которые могут существовать (и выполняться) только в одном контексте, например, модуль управляемого приложения может выполняться только на стороне клиента (тонкого или веб-клиента).

● Модули, которые могут существовать (и выполняться) в нескольких контекстах. Такими модулями является модуль управляемой формы, модуль команды и общий модуль. Например, модуль управляемой формы может существовать в четырех экземплярах, при этом в процессе работы управление может передаваться между различными экземплярами модуля:

● клиентский контекстный модуль,

● серверный контекстный модуль,

● клиентский внеконтекстный модуль,

● серверный внеконтекстный модуль.

При этом у модуля команды и общего модуля не может существовать контекстных экземпляров (в отличие от модуля формы). Поэтому некоторые модули могут компилироваться несколько раз, в зависимости от того, есть ли в этом модуле фрагменты кода, которые могут выполняться в том или ином контексте.

Рассмотрим, какое влияние оказывают директивы компиляции и инструкции препроцессора на исходный программный текст модуля в процессе его преобразования в «исполняемый» код.

Рассмотрим это на примере модуля управляемой формы.

В момент создания формы формируется четыре экземпляра модуля формы и выполняется определение всех необходимых инструкций препроцессору для каждого экземпляра модуля. Затем происходит обработка каждого экземпляра модуля и исключение текста, обрамленного инструкциями препроцессора.

Затем происходит компиляция получившегося программного кода в соответствии с контекстом и директивами компиляции. В результате получается исполняемый модуль.

Предположим, в исходном тексте модуля формы встречается конструкция:

Копировать в буфер обмена
&НаКлиенте
Процедура РаботаСФайлами()
    #Если ВебКлиент Тогда
   // программный текст 1
   // исполняется только на веб клиенте
    #Иначе
   // программный текст 2
   // исполняется на других типах клиента
    #КонецЕсли
КонецПроцедуры

Тогда будет выполнено следующее:

● Данная процедура будет компилироваться на любом клиенте (как следует из директивы компиляции).

● В то же время инструкции препроцессора будут определять, какой именно текст и на каком клиенте будет оставлен в модуле (и, как следствие, скомпилирован). В данном примере на веб-клиенте будет доступен только «программный текст 1», а на других клиентах ‑ «программный текст 2».

Однако если в модуле формы будет использован следующий код:

Копировать в буфер обмена
#Если НаСервере Тогда
&НаКлиенте
Процедура Клиентская()
КонецПроцедуры
#КонецЕсли

Тогда произойдет следующее:

● на сервере будет присутствовать исходный текст нашей процедуры, но он не будет скомпилирован, т. к. директива компиляции &НаКлиенте исключает возможность появления процедуры на стороне сервера;

● на клиенте не будет даже исходного текста нашей процедуры, т. к. его «вырежет» инструкция препроцессора, а значит, эта процедура не будет скомпилирована и не будет доступна для вызова.

Исходя из описанного механизма и следует подходить к пониманию взаимодействия директив и инструкций, а также к их совместному применению.

Также нужно отметить, что методы, отмеченные в программном модуле директивами &НаКлиентеНаСервереБезКонтекста и &НаКлиентеНаСервере, попадут одновременно в разные экземпляры программных модулей.

4.8.1.2. Инструкции препроцессора

Синтаксис инструкций препроцессору следующий:

Инструкция препроцессору

#<Инструкция>

Инструкция

<Инструкция> = { Если <Логическое выражение> Тогда | ИначеЕсли <Логическое выражение> Тогда | Иначе | КонецЕсли | Вставка | КонецВставки | Удаление | КонецУдаления }

Логическое выражение

<Логическое выражение> = [НЕ] <Символ препроцессора> [<Булева операция> [НЕ] <Символ препроцессора> [<Булева операция> [НЕ] <Символ препроцессора>]…]

Символ препроцессора

<Символ препроцессора> = { Сервер | НаСервере | Клиент | НаКлиенте | ТонкийКлиент | МобильныйКлиент | ВебКлиент | ВнешнееСоединение | ТолстыйКлиентУправляемоеПриложение | ТолстыйКлиентОбычноеПриложение | МобильноеПриложениеКлиент | МобильноеПриложениеСервер | МобильныйАвтономныйСервер | Область | КонецОбласти }

Булева операция

<Булева операция> = {И | Или}

Русское имя

Английское имя

Если

If

Тогда

Then

Иначе

Else

ИначеЕсли

ElsIf

КонецЕсли

EndIf

Область

Region

КонецОбласти

EndRegion

Вставка

Insert

КонецВставки

EndInsert

Удаление

Delete

КонецУдаления

EndDelete

И

And

Или

Or

Не

Not

Сервер

Server

НаСервере

AtServer

Клиент

Client

НаКлиенте

AtClient

ТонкийКлиент

ThinClient

МобильныйКлиент

MobileClient

ВебКлиент

WebClient

ВнешнееСоединение

ExternalConnection

ТолстыйКлиентУправляемоеПриложение

ThickClientManagedApplication

ТолстыйКлиентОбычноеПриложение

ThickClientOrdinaryApplication

МобильноеПриложениеКлиент

MobileAppClient

МобильноеПриложениеСервер

MobileAppServer

МобильныйАвтономныйСервер

MobileStandaloneServer

Далее приведен перечень инструкций препроцессора и их краткое описание:

Сервер, НаСервере ‑ определяет сервер;

Клиент, НаКлиенте ‑ определяет любого клиента;

ТонкийКлиент ‑ определяет тонкого клиента;

МобильныйКлиент ‑ определяет мобильный клиент;

ВебКлиент ‑ определяет веб-клиента;

ВнешнееСоединение ‑ определяет внешнее соединение;

ТолстыйКлиентУправляемоеПриложение ‑ определяет режим управляемого приложения толстого клиента;

ТолстыйКлиентОбычноеПриложение ‑ определяет обычный режим толстого клиента;

МобильноеПриложениеКлиент ‑ определяет клиентскую часть мобильного приложения;

МобильноеПриложениеСервер ‑ определяет серверную часть мобильного приложения;

МобильныйАвтономныйСервер ‑ определяет серверную часть мобильного клиента, работающую в автономном режиме на мобильном устройстве;

Область, КонецОбласти ‑ не предназначены для определения места выполнения кода на встроенном языке. Служат для выделения фрагмента текста, который можно будет свернуть (аналогично процедурам, функциям и т. д.). Подробнее см. здесь.

Вставка, КонецВставки, Удаление, КонецУдаления ‑ используются только в расширениях конфигурации, в сочетании с аннотацией ИзменениеИКонтроль. Подробнее см. здесь.

В различных вариантах использования определены различные наборы инструкций препроцессора. При описании того, какие инструкции препроцессора определены в различных вариантах работы, будем считать, что:

● Клиентская часть ‑ это приложение системы «1С:Предприятие», которое работает на компьютере пользователя.

● Серверная часть ‑ это приложение системы «1С:Предприятие», которое работает на компьютере, на котором работает кластер серверов системы «1С:Предприятие».

Возможна ситуация, когда клиентская и серверные части приложения физически объединены в одном приложении (например, тонкий клиент в файловом варианте или приложение на мобильной платформе). Однако разделение на клиентскую часть и серверную часть даже в этом случае присутствует, исходя из устройства системы «1С:Предприятие» (см. здесь). Когда речь идет про обычное приложение, то под «серверной частью» понимается работа программного кода на стороне кластера серверов «1С:Предприятие» при условии явного вызова такого кода, например, при вызове метода серверного общего модуля.

Далее приведен список определенных инструкций препроцессора в зависимости от используемого варианта работы и используемого способа доступа к информационной базе:

Файловый вариант:

● Тонкий клиент:

● Клиентская часть: Клиент, НаКлиенте, ТонкийКлиент.

● Серверная часть: Сервер, НаСервере.

● Веб-клиент:

● Клиентская часть: Клиент, НаКлиенте, ВебКлиент.

● Серверная часть: Сервер, НаСервере.

● Внешнее соединение:

● Клиентская часть: недоступно.

● Серверная часть: Сервер, НаСервере, ВнешнееСоединение.

● Интернет-сервисы, фоновые и регламентные задания:

● Клиентская часть: недоступно.

● Серверная часть: Сервер, НаСервере.

● Толстый клиент в управляемом режиме:

● Клиентская часть: Сервер, НаСервере, Клиент, НаКлиенте, ТолстыйКлиентУправляемоеПриложение.

● Серверная часть: Сервер, НаСервере, Клиент, НаКлиенте, ТолстыйКлиентУправляемоеПриложение.

● Толстый клиент в обычном режиме:

● Клиентская часть: Сервер, НаСервере, Клиент, НаКлиенте, ТолстыйКлиентОбычноеПриложение.

● Серверная часть: Сервер, НаСервере, Клиент, НаКлиенте, ТолстыйКлиентОбычноеПриложение.

Клиент-серверный вариант:

● Тонкий клиент:

● Клиентская часть: Клиент, НаКлиенте, ТонкийКлиент.

● Серверная часть: Сервер, НаСервере.

● Веб-клиент:

● Клиентская часть: Клиент, НаКлиенте, ВебКлиент.

● Серверная часть: Сервер, НаСервере.

● Мобильный клиент:

● Клиентская часть: Клиент, НаКлиенте, МобильныйКлиент.

● Серверная часть: Сервер, НаСервере.

● Мобильный клиент с автономным режимом:

● Клиентская часть: Клиент, НаКлиенте, МобильныйКлиент.

● Серверная часть: Сервер, НаСервере.

● Серверная часть на мобильном устройстве: Сервер, НаСервере, МобильныйАвтономныйСервер.

● Внешнее соединение:

● Клиентская часть: недоступно.

● Серверная часть: ВнешнееСоединение.

● Интернет-сервисы, фоновые и регламентные задания:

● Клиентская часть: недоступно.

● Серверная часть: Сервер, НаСервере.

● Толстый клиент в управляемом режиме:

● Клиентская часть: Клиент, НаКлиенте, ТолстыйКлиентУправляемоеПриложение.

● Серверная часть: Сервер, НаСервере.

● Толстый клиент в обычном режиме:

● Клиентская часть: Клиент, НаКлиенте, ТолстыйКлиентОбычноеПриложение.

● Серверная часть: Сервер, НаСервере.

Мобильная платформа:

● Клиентская часть: Клиент, НаКлиенте, МобильноеПриложениеКлиент.

● Серверная часть: Сервер, НаСервере, МобильноеПриложениеСервер.

Если используется неглобальный общий модуль, для которого установлено использование на клиенте (любом) и на сервере, то методы, заключенные в условие #Если Сервер Тогда #КонецЕсли или описанные с директивой компиляции &НаСервере, будут доступны только в том случае, если вызов этих методов выполняется со стороны сервера. Вызов таких методов со стороны клиента недоступен.

В остальных случаях инструкции Сервер и НаСервере полностью идентичны и инструкции Клиент и НаКлиенте также полностью идентичны.

Примечание. Перед передачей программного модуля на тонкий или веб-клиент сервер выполняет обработку инструкций препроцессора, находящихся в модуле. В ходе обработки текст на встроенном языке, который не исполняется на стороне вышеуказанных клиентов, заменяется на пробелы (фактически удаляется). При этом символы переноса строк и табуляции остаются на своих местах.

4.8.1.3. Директивы компиляции

Синтаксис директивы компиляции следующий:

Директива компиляции

&<Директива>

<Конструкция языка>

Директива

<Директива> = { НаКлиенте | НаСервере | НаСервереБезКонтекста | НаКлиентеНаСервереБезКонтекста | НаКлиентеНаСервере }

Конструкция языка

<Конструкция языка> = { <Описание переменной> | <Описание процедуры> | <Описание функции> }

Подробное описание конструкций языка см. здесь.

Русское имя

Английское имя

НаКлиенте

AtClient

НаСервере

AtServer

НаСервереБезКонтекста

AtServerNoContext

НаКлиентеНаСервереБезКонтекста

AtClientAtServerNoContext

НаКлиентеНаСервере

AtClientAtServer

Далее приведен перечень директив компиляции и их краткое описание:

НаКлиенте ‑ означает, что метод выполняется на стороне клиента в контексте формы.

Переменная существует все время жизни клиентской части формы.

Из метода доступны клиентские переменные модуля формы.

Допустимы вызовы любых методов.

НаСервере ‑ означает, что метод выполняется на стороне сервера в контексте формы.

Переменная существует только во время вызова выполнения серверного вызова.

Из метода доступны серверные переменные модуля формы.

Допустимы вызовы:

● серверных;

● серверных внеконтекстных;

● клиент-серверных внеконтекстных методов;

● методов неглобальных серверных общих модулей.

НаСервереБезКонтекста ‑ означает, что метод исполняется на сервере вне контекста формы.

Переменные не могут предваряться такой директивой компиляции.

Из метода недоступны переменные модуля формы.

Допустимы вызовы:

● серверных внеконтекстных;

● клиент-серверных внеконтекстных методов;

● методов не глобальных серверных общих модулей.

НаКлиентеНаСервереБезКонтекста ‑ означает, что метод исполняется как на клиенте, так и на сервере, вне контекста формы.

Переменные не могут предваряться такой директивой компиляции.

Из метода недоступны переменные модуля формы.

Допустимы вызовы:

● серверных внеконтекстных;

● клиент-серверных внеконтекстных методов;

● методов неглобальных серверных общих модулей;

● методов неглобальных общих модулей с флажками Сервер и Клиент (управляемое приложение).

Не поддерживается вызов экспортных процедур, обозначенных такой директивой, как методов объекта ЭтотОбъект.

НаКлиентеНаСервере ‑ означает, что методы выполняются на клиенте и на сервере. Переменные не могут предваряться такой директивой компиляции.

Допустимы вызовы:

● серверных внеконтекстных;

● клиент-серверных внеконтекстных методов;

● методов неглобальных серверных общих модулей;

● методов неглобальных общих модулей с флажками Сервер и Клиент (управляемое приложение).

Ниже приведена таблица, показывающая, какие директивы компиляции доступны в каких модулях системы «1С:Предприятие»:

Модуль формы

Перемен-
ные модуля формы

Модуль
команды

Общий
модуль

НаКлиенте

+

+

+

+

НаСервере

+

+

+

+

НаСервереБезКонтекста

+

НаКлиентеНаСервереБезКонтекста

+

НаКлиентеНаСервере

+

4.8.2. Аннотации

Аннотация это специальная форма синтаксических метаданных, которая добавляется в исходный код для функционирования механизма расширения конфигурации (см. здесь). Аннотации используются для анализа кода и во время выполнения. Аннотироваться могут методы и переменные в модулях на встроенном языке. Аннотации и директивы компиляции (см. здесь) могут чередоваться между собой.

Аннотация

&<Перед|После|Вместо>[([<Имя>=<Значение>[, <Имя>=<Значение>, …]])]

Аннотация начинается с символа «&» (аналогично директивам компиляции), затем идет имя аннотации (доступные имена аннотаций приведены далее), затем идут параметры аннотации, разделенные символом «,», если аннотация требует параметры. Параметры аннотации заключаются в круглые скобки. Если у аннотации единственный параметр, то допускается указывать значение параметра без указания его (параметра) имени. Доступны следующие аннотации:

Русское имя

Английское имя

Перед

Before

После

After

Вместо

Around

ИзменениеИКонтроль

ChangeAndValidate

Важно помнить, что система не поддерживает пользовательских аннотаций. Другими словами, разработчик не может создать собственную аннотацию для прикладного применения, которой он может распоряжаться по собственному усмотрению.

Более подробное описание аннотаций (и их применения) см. здесь.

4.8.3. Особенности использования объектов, их свойств и методов

Каждый объект, метод или свойство встроенного языка (далее в этом разделе ‑ объект) обладает определенной доступностью (см. синтакс-помощник), которая определяет, где можно использовать объект, метод или свойство. Кроме того, в синтакс-помощнике указываются некоторые вспомогательные данные, которые могут помочь разработчику.

Тонкий клиент ‑ указывает, что объект доступен в тонком клиенте.

Веб-клиент ‑ указывает, что объект доступен в веб-клиенте.

Мобильный клиент ‑ указывает, что объект доступен в мобильном клиенте.

Мобильное приложение (клиент) ‑ указывает, что объект доступен в клиентской части мобильной платформы «1С:Предприятия».

Толстый клиент ‑ указывает, что объект доступен в толстом клиенте.

Сервер ‑ указывает, что объект доступен на сервере «1С:Предприятия».

Мобильное приложение (сервер) ‑ указывает, что объект доступен на стороне сервера мобильной платформы «1С:Предприятия».

Мобильный автономный сервер ‑ указывает, что объект доступен на стороне сервера мобильного клиента «1С:Предприятие», работающего на мобильном устройстве в автономном режиме.

Внешнее соединение ‑ указывает, что объект доступен в режиме внешнего соединения.

ВНИМАНИЕ! Если для объекта указано, что он недоступен для какого-либо из режимов запуска, то свойства и методы данного объекта также недоступны. Поэтому специального упоминания об этом при описании свойств и методов не приводится.

Примечание. Если объект недоступен на стороне какого-либо клиентского приложения, то в этом клиентском приложении также недоступен и тип этого объекта. Например, если в тонком клиенте недоступен объект СправочникОбъект.Контрагенты, то Тип("СправочникОбъект.Контрагенты") также недоступен в тонком клиенте.

Сериализуется. Указывает возможность сохранения значения объектов (например, методами СохранитьЗначение() и ЗначениеВФайл()), сохранения параметров форм отчетов и обработок, а также помещения в ХранилищеЗначения и временное хранилище.

Данный объект может быть сериализован в/из XML. Указывает возможность поддержки чтения/записи значений данных системы «1С:Предприятие» в/из XML. Подробнее см. здесь.

Возможен обмен с сервером. Указывает возможность обмена значениями данного типа между клиентом и сервером только в обычном приложении.

Данный объект может быть сериализован в/из XDTO. Указывает на то, что данный тип имеет возможность отображения в модель данных XDTO. При этом указывается квалифицированное имя типа (типов) (указывается URI пространство имен и имя типа), в который отображается данный тип. Например, для типа ХранилищеЗначения: {http://v8.1c.ru/8/data/core}ValueStorage. Указывает возможность обмена значениями данного типа между клиентом и сервером только в управляемом приложении.

Что должно выполняться для того, чтобы значение какого-либо типа могло быть передано между клиентом и сервером, а также что следует учитывать при проектировании методов конфигурации (в части передачи параметров методов) см. здесь.

Текст Безопасный режим на время исполнения данного обработчика будет отключен в описании обработчика означает, что вызове данного обработчика события система "1С:Предприятие" принудительно отключит безопасный режим. Подробнее о таком поведении см. здесь.

Синтакс-помощник содержит информацию о кешировании результатов работы некоторых методов «1С:Предприятия». Например, для метода глобального контекста ПредопределенноеЗначение() будет указана следующая информация: Результат выполнения кешируется при первом обращении до изменения конфигурации или версии платформы.

В некоторых случаях система накладывает ограничения на возможные действия в обработчиках событий. В этих случаях синтакс-помощник содержит указание на запрещенное действие или описание действия, которое может привести к недопустимому действию:

1. В обработчике данного события нельзя использовать серверные методы формы с директивой компиляции &НаСервере.

2. Изменение свойства на клиенте может потребовать обращения к серверу.

3. Вызов метода выполняет обращение к серверу. Данное предупреждение расположено в описании клиентских методов. Оно означает, что разработчик не может вызывать данный метод в обработчике события, для которого запрещены контекстные серверные вызовы.

Во время исполнения прикладного решения имеется возможность включения диагностики нарушения вышеуказанных ограничений. Если в командной строке запуска клиентского приложения присутствует ключ /EnableCheckServerCalls (подробнее см. здесь), то при обнаружении нарушения указанных правил, в окно сообщений выводится диагностика. Эта же диагностика будет присутствовать в диалоге Информация для технической поддержки.

При запуске клиентского приложения из конфигуратора, включение этого ключа выполняется с помощью флажка настройки параметров конфигуратора Проверять серверные вызовы в обработчиках событий (подробнее см. здесь).